首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

iOS 父子控制器最佳實踐:驗證 Apple 官方建議「View 為父子則 Controller 也應為父子」

     編輯:關於C語言

iOS 父子控制器最佳實踐:驗證 Apple 官方建議「View 為父子則 Controller 也應為父子」

Apple 官方文檔明確指出:當控制器的 View 互為父子關係時,控制器最好也互為父子關係。忽視這一原則會導致嚴重的生命週期與事件傳遞問題。本文通過屏幕旋轉案例實證其中差異。

問題場景:View 是父子,Controller 卻不是

在 iPad 開發中,屏幕旋轉是高頻操作。假設 ZYViewController 透過 addSubview: 將 ZYOneViewController 的 View 加入自身,但未建立控制器父子關係:

// ZYViewController.m
- (ZYOneViewController *)one {
    if (!_one) {
        self.one = [[ZYOneViewController alloc] init];
        self.one.view.frame = CGRectMake(10, 70, 300, 300);
        // 缺少 [self addChildViewController:self.one];
    }
    return _one;
}
- (IBAction)vc1 {
    [self.view addSubview:self.one.view];
}

此時旋轉設備,ZYViewController 會收到 willRotateToInterfaceOrientation: 等旋轉回調,但 ZYOneViewController 完全收不到任何旋轉事件。因為 UIKit 僅在控制器層級維護父子關係樹,才會將旋轉、外觀轉換、記憶體警告等系統事件自動向下分發。

解決方案:建立控制器父子關係

只需在懶加載中加入一行:

- (ZYOneViewController *)one {
    if (!_one) {
        self.one = [[ZYOneViewController alloc] init];
        self.one.view.frame = CGRectMake(10, 70, 300, 300);
        [self addChildViewController:self.one]; // 關鍵行
    }
    return _one;
}

再次旋轉測試,ZYOneViewController 現在能正確接收 willRotateToInterfaceOrientation: 與 didRotateFromInterfaceOrientation: 回調。事件分發鏈路恢復暢通。

深層原理

  • 事件分發機制:UIViewController 內部維護 childViewControllers 陣列,系統事件(旋轉、外觀、記憶體警告等)沿此樹向下傳遞。
  • 生命週期保護:父控制器強引用子控制器,防止子控制器過早釋放導致 View 仍在但 Controller 已死,造成數據無法更新、手勢失效等詭異 Bug。
  • 佈局協同:viewWillLayoutSubviews、viewDidLayoutSubviews 等佈局回調也需父子關係才能正確觸發。

最佳實踐清單

  1. 凡是 addSubview: 子控制器的 View,必須先呼叫 addChildViewController:(iOS 5+)或 addChild:(iOS 10+)。
  2. 移除時對應呼叫 removeFromParentViewController / removeFromParent。
  3. 使用 UIViewController 容器 API(如 UIPageViewController、UINavigationController)時無需手動管理,系統已內建處理。

遵循「View 父子 ⇒ Controller 父子」原則,能避免 90% 的容器控制器相關疑難雜症,是 iOS 架構設計的基石之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved