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

iOS 開發鐵律:視圖層級父子關係必須對應控制器層級父子關係

     編輯:關於C

核心原則

Apple 官方文檔明確指出:當控制器的 view 互為父子關係時,控制器本身最好也建立父子關係。 違反此原則會導致嚴重的生命週期與事件傳遞問題。

問題現場:缺失父子關係的後果

場景:主控制器 ZYViewController 懶加載子控制器 ZYOneViewController,僅將其 view 添加為子視圖,未調用 addChildViewController:。

// 錯誤做法
- (IBAction)vc1 {
    [self.view addSubview:self.one.view]; // 僅視圖層級父子
}

旋轉設備時,父控制器收到 willRotateToInterfaceOrientation: 等回調,但子控制器完全收不到任何旋轉事件。控制台輸出證實:只有父控制器打印了旋轉日誌。

根因分析

  • iOS 通過控制器層級的父子鏈傳遞外觀轉旋轉、顯示/隱藏、內存警告等系統事件;
  • 僅有視圖層級關係無法建立控制器事件傳遞通道;
  • 子控制器處於「孤兒」狀態,系統不知其存在,不會調用其生命週期方法。

正確做法:建立控制器父子關係

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

添加此行後,旋轉事件正常傳遞給子控制器,雙方均打印出對應日誌。

延伸最佳實踐

  1. 完整父子協議:調用 addChildViewController: 後,若手動管理視圖層級,還需調用 [child didMoveToParentViewController:self];
  2. 移除時對稱:移除子控制器需依次調用 [child willMoveToParentViewController:nil]、[child.view removeFromSuperview]、[child removeFromParentViewController];
  3. 容器控制器:自定義容器控制器時,必須嚴格遵循此協議,否則子控制器行為不可預期。

總結

「視圖父子 ⇒ 控制器父子」是 iOS 視圖控制器架構的基石。忽視它會導致旋轉失效、生命週期缺失、狀態恢復異常等難以排查的 Bug。養成習慣:每次 addSubview: 子控制器的 view 時,自問「addChildViewController: 了嗎?」

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