核心回答
iOS 控件/對象間通信主要採用以下模式(按使用頻度排序):
- 代理模式 - 一對一,強契約,編譯期檢查(`UITableViewDelegate`、`UITextFieldDelegate`)。
- Target-Action - 控件事件響應,運行時動態綁定(`UIButton.addTarget`、`UIGestureRecognizer`)。
- NotificationCenter (觀察者模式變體) - 一對多、跨層級、鬆耦合(鍵盤通知、App 生命週期)。
- KVO (Key-Value Observing) - 屬性變化自動通知,適用於模型-視圖同步。
- Block / Closure 回調 - 現代化、內聯、捕獲上下文(網絡請求完成、動畫完成)。
- Responder Chain (響應者鏈) - 事件傳遞鏈(觸摸事件、動作消息)。
模式對比表
| 模式 | 耦合度 | 關係 | 典型場景 | 優/缺點 |
| 代理 | 中 | 一對一 | TableView 數據源、文本框驗證 | ✅ 編譯檢查 ❌ 易循環引用(weak) |
| Target-Action | 低 | 一對一 | 按鈕點擊、手勢識別 | ✅ 簡單 ❌ 僅限 UIControl 事件 |
| NotificationCenter | 極低 | 一對多 | 鍵盤彈出、登錄狀態變化 | ✅ 解耦 ❌ 調試難、過度使用導致混亂 |
| KVO | 低 | 一對多 | 模型屬性→視圖更新 | ✅ 自動 ❌ 崩潰風險、性能開銷 |
| Block/Closure | 低 | 一對一 | 異步回調、動畫完成 | ✅ 代碼內聚 ❌ 循環引用(weak self) |
架構層面關聯
- MVC:View → Controller 用 **Target-Action/代理**;Model → Controller 用 **KVO/Notification/Block**。
- MVVM:ViewModel → View 用 **KVO/綁定框架**;View → ViewModel 用 **Block/Command**。
- VIPER/組件化:模塊間通過 **Protocol(代理) / Notification / Router** 通信。
關係圖(文字版)
[用戶交互]
↓ (Target-Action / 手勢)
[UIControl / View]
↓ (代理 / Block 回調)
[ViewController] ←→ [Model/Service] (KVO / Notification / Block / Combine)
↓ (Notification / 代理)
[其他 VC / 服務 / 持久層]
最佳實踐建議
- **優先代理/Block**:邏輯清晰、編譯期安全。
- **跨層級/多對象**:NotificationCenter(注意 `removeObserver`)。
- **模型屬性驅動 UI**:KVO 或 Combine (`@Published`)。
- **避免濫用單例/全局通知**作為萬能膠水,導致依賴難追蹤。
- **Swift 現代化**:優先 `Combine` / `async-await` / `@Binding` 替代傳統模式。