AddChildViewController thực sự làm gì?


102

Tôi chỉ mới nhúng chân lần đầu tiên vào việc phát triển iOS và một trong những điều đầu tiên tôi phải làm là triển khai bộ điều khiển chế độ xem vùng chứa tùy chỉnh - hãy gọi nó SideBarViewController- điều đó sẽ hoán đổi nó. gần giống như một Bộ điều khiển thanh tab tiêu chuẩn . (Nó khá giống một Bộ điều khiển thanh tab nhưng với menu bên có thể ẩn thay vì thanh tab.)

Theo hướng dẫn trong tài liệu của Apple, tôi gọi addChildViewControllerbất cứ khi nào tôi thêm ViewController con vào vùng chứa của mình. Mã của tôi để hoán đổi bộ điều khiển chế độ xem trẻ em hiện tại được hiển thị SideBarViewControllernhư sau:

- (void)showViewController:(UIViewController *)newViewController {
    UIViewController* oldViewController = [self.childViewControllers 
                                           objectAtIndex:0];
    
    [oldViewController removeFromParentViewController];
    [oldViewController.view removeFromSuperview];
    
    newViewController.view.frame = CGRectMake(
        0, 0, self.view.frame.size.width, self.view.frame.size.height
    );
    [self addChildViewController: newViewController];
    [self.view addSubview: newViewController.view];
}

Sau đó, tôi bắt đầu cố gắng tìm ra những gì addChildViewControllerxảy ra ở đây, và tôi nhận ra rằng tôi không biết. Ngoài việc dính cái mới ViewControllertrong .childViewControllersmảng, nó dường như không ảnh hưởng gì cả. Các tác vụ và cửa ra từ chế độ xem của bộ điều khiển trẻ em đến bộ điều khiển trẻ em mà tôi đã đặt trên bảng phân cảnh vẫn hoạt động tốt ngay cả khi tôi không bao giờ gọi addChildViewControllervà tôi không thể tưởng tượng nó có thể ảnh hưởng gì khác.

Thật vậy, nếu tôi viết lại mã của mình để không gọi addChildViewControllervà thay vào đó trông như thế này ...

- (void)showViewController:(UIViewController *)newViewController {

    // Get the current child from a member variable of `SideBarViewController`
    UIViewController* oldViewController = currentChildViewController;

    [oldViewController.view removeFromSuperview];

    newViewController.view.frame = CGRectMake(
        0, 0, self.view.frame.size.width, self.view.frame.size.height
    );
    [self.view addSubview: newViewController.view];

    currentChildViewController = newViewController;
}

... thì ứng dụng của tôi vẫn hoạt động hoàn hảo, theo như tôi có thể nói!

Tài liệu của Apple không làm sáng tỏ những gì addChildViewControllerlàm được hoặc tại sao chúng ta nên gọi nó như vậy. Toàn bộ phạm vi mô tả có liên quan về chức năng của phương pháp hoặc lý do tại sao nó nên được sử dụng trong phần của nó trong UIViewControllerTham chiếu Lớp , hiện tại:

Thêm bộ điều khiển chế độ xem đã cho khi còn nhỏ. ... Phương thức này chỉ nhằm mục đích được gọi bằng cách triển khai bộ điều khiển chế độ xem vùng chứa tùy chỉnh. Nếu bạn ghi đè phương thức này, bạn phải gọi super trong triển khai của mình.

Cũng có đoạn này trước đó trên cùng một trang:

Bộ điều khiển chế độ xem vùng chứa của bạn phải liên kết bộ điều khiển chế độ xem con với chính nó trước khi thêm chế độ xem gốc của trẻ vào hệ thống phân cấp chế độ xem. Điều này cho phép iOS định tuyến đúng các sự kiện đến bộ điều khiển chế độ xem con và chế độ xem mà bộ điều khiển đó quản lý. Tương tự như vậy, sau khi nó xóa chế độ xem gốc của một đứa trẻ khỏi hệ thống phân cấp chế độ xem của nó, nó sẽ ngắt kết nối bộ điều khiển chế độ xem con đó khỏi chính nó. Để tạo hoặc phá vỡ các liên kết này, vùng chứa của bạn gọi các phương thức cụ thể được xác định bởi lớp cơ sở. Các phương thức này không nhằm mục đích được gọi bởi các máy khách thuộc lớp vùng chứa của bạn; chúng chỉ được sử dụng khi triển khai vùng chứa của bạn để cung cấp hành vi ngăn chặn dự kiến.

Dưới đây là các phương thức thiết yếu mà bạn có thể cần gọi:

addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:

nhưng nó không cung cấp bất kỳ manh mối nào về 'sự kiện' hoặc 'hành vi ngăn chặn dự kiến' mà nó đang nói đến, hoặc tại sao (hoặc thậm chí khi) gọi các phương thức này là 'thiết yếu'.

Các ví dụ về bộ điều khiển chế độ xem vùng chứa tùy chỉnh trong phần "Bộ điều khiển chế độ xem vùng chứa tùy chỉnh" của tài liệu Apple đều gọi phương thức này, vì vậy tôi giả sử rằng nó phục vụ một số mục đích quan trọng ngoài việc chỉ đưa ViewController con vào một mảng, nhưng tôi không thể hình dung mục đích đó là gì. Phương thức này làm gì và tại sao tôi nên gọi nó?


3
Trang video WWDC năm 2011 của Apple có một phiên tuyệt vời ("Triển khai UIViewController Containment") về chủ đề này.
Alladinian

Câu trả lời:


94

Tôi cũng đang băn khoăn về câu hỏi này. Tôi đã xem Phần 102 của các video WWDC 2011 và Mr. View Controller, Bruce D. Nilo , đã nói điều này:

viewWillAppear:,, viewDidAppear:v.v. không liên quan gì addChildViewController:. Tất cả những gì addChildViewController:làm là nói "Bộ điều khiển chế độ xem này là con của bộ điều khiển đó" và nó không liên quan gì đến giao diện chế độ xem. Khi chúng được gọi được liên kết với khi các khung nhìn di chuyển vào và ra khỏi hệ thống phân cấp cửa sổ.

Vì vậy, có vẻ như rằng cuộc gọi để addChildViewController:làm rất ít. Các tác dụng phụ của cuộc gọi là một phần quan trọng. Họ đến từ parentViewControllervà các childViewControllersmối quan hệ. Đây là một số tác dụng phụ mà tôi biết:

  • Chuyển tiếp các phương thức xuất hiện tới bộ điều khiển chế độ xem con
  • Các phương thức luân chuyển chuyển tiếp
  • (Có thể) cảnh báo bộ nhớ chuyển tiếp
  • Tránh phân cấp VC không nhất quán, đặc biệt là trong transitionFromViewController:toViewController:… trường hợp cả hai VC cần có cùng nguồn gốc
  • Cho phép bộ điều khiển chế độ xem vùng chứa tùy chỉnh tham gia vào Bảo quản và Khôi phục trạng thái
  • Tham gia vào chuỗi phản hồi
  • Hooking lên navigationController, tabBarController, vv thuộc tính

Đó là phiên 102 chứ không phải 101
SeanChense.

+1 cho chuỗi người trả lời. addChildViewController là cần thiết nếu bạn muốn nhận các sự kiện liên lạc trên một subview thuộc sở hữu của một đứa trẻ UIViewController
charlieb

108

Tôi nghĩ rằng một ví dụ có giá trị một nghìn từ.

Tôi đang làm việc trên một ứng dụng thư viện và muốn hiển thị một dạng xem sổ ghi chú đẹp xuất hiện khi người dùng muốn thêm ghi chú.

nhập mô tả hình ảnh ở đây

Sau khi thử một số giải pháp, cuối cùng tôi đã phát minh ra giải pháp tùy chỉnh của riêng mình để hiển thị sổ ghi chú. Vì vậy, khi tôi muốn hiển thị notepad, tôi tạo một phiên bản mới NotepadViewControllervà thêm chế độ xem gốc của nó làm chế độ xem phụ vào chế độ xem chính. Càng xa càng tốt.

Sau đó, tôi nhận thấy rằng hình ảnh notepad bị ẩn một phần dưới bàn phím ở chế độ ngang.

nhập mô tả hình ảnh ở đây

Vì vậy, tôi muốn thay đổi hình ảnh notepad và chuyển nó lên. Và để làm như vậy, tôi đã viết mã thích hợp trong willAnimateRotationToInterfaceOrientation:duration:phương thức, nhưng khi tôi chạy ứng dụng thì không có gì xảy ra! Và sau khi gỡ lỗi, tôi nhận thấy rằng không có UIViewControllerphương thức xoay vòng nào thực sự được gọi trong NotepadViewController. Chỉ những phương thức đó trong bộ điều khiển chế độ xem chính đang được gọi.

Để giải quyết vấn đề này, tôi cần gọi tất cả các phương thức từ NotepadViewController thủ công khi chúng được gọi trong bộ điều khiển chế độ xem chính. Điều này sẽ sớm làm cho mọi thứ trở nên phức tạp và tạo ra sự phụ thuộc thêm giữa các thành phần không liên quan trong ứng dụng.

Đó là trong quá khứ, trước khi khái niệm bộ điều khiển chế độ xem con được giới thiệu. Nhưng bây giờ, bạn chỉ cần vào addChildViewControllerbộ điều khiển chế độ xem chính và mọi thứ sẽ hoạt động như mong đợi mà không cần làm thêm bất kỳ thao tác thủ công nào.

Chỉnh sửa: Có hai danh mục sự kiện được chuyển tiếp đến bộ điều khiển chế độ xem con:

1- Phương pháp xuất hiện:

- viewWillAppear:
- viewDidAppear:
- viewWillDisappear:
- viewDidDisappear:

2- Phương pháp quay vòng:

- willRotateToInterfaceOrientation:duration:
- willAnimateRotationToInterfaceOrientation:duration:
- didRotateFromInterfaceOrientation:

Bạn cũng có thể kiểm soát loại sự kiện nào bạn muốn được chuyển tiếp tự động bằng cách ghi đè shouldAutomaticallyForwardRotationMethodsshouldAutomaticallyForwardAppearanceMethods.


Từ tài liệu và sau khi thực hiện kiểm tra nhanh, tôi không nghĩ rằng có bất kỳ sự kiện nào khác chỉ được chuyển tiếp nếu bạn addChildViewControllerđến bộ điều khiển mẹ.
Hejazi

ước gì nó tự động chuyển tiếp lượt xemWillLayoutSubviews
MobileMon

10

-[UIViewController addChildViewController:]chỉ thêm bộ điều khiển chế độ xem được truyền vào trong một mảng các bộ điều khiển viewController mà một viewController (cha) muốn giữ tham chiếu. Bạn thực sự nên tự thêm các dạng xem của viewController đó trên màn hình bằng cách thêm chúng dưới dạng các dạng xem con của một dạng xem khác (ví dụ: dạng xem của parentViewController). Ngoài ra còn có một đối tượng tiện lợi trong Trình tạo giao diện để sử dụng childrenViewControllers trong Storyboards.

Trước đây, để giữ tham chiếu của các ViewControllers khác mà bạn đã sử dụng các khung nhìn, bạn phải giữ tham chiếu thủ công về chúng trong @properties. Có một build-in hữu như childViewControllersvà do đó parentViewControllerlà một cách thuận tiện để quản lý các tương tác như vậy và xây dựng gồm viewControllers như UISplitViewController mà bạn tìm thấy trên các ứng dụng iPad.

Hơn nữa, childrenViewControllers cũng tự động nhận tất cả các sự kiện hệ thống mà cha mẹ nhận được: -viewWillAppear, -viewWillDisappear, v.v. Trước đây, bạn nên gọi các phương thức này theo cách thủ công trên "childrenViewControllers" của mình.

Đó là nó.


Cơ sở của bạn để nghĩ rằng đó là tất cả những gì nó làm? Ngoài ra, bạn có thể cung cấp danh sách 'các sự kiện hệ thống' mà đứa trẻ nhận được không? Tìm kiếm của Google cho iOS "system events"không nhiều; Nó dường như không phải là một thuật ngữ mà Apple sử dụng?
Mark Amery

Về cơ bản nó là một phương pháp tiện lợi cho phép bạn thêm chế độ xem của View Controller B làm chế độ xem con của View Controller A, nhưng vẫn có View Controller B quản lý chế độ xem của nó. Để điều này hoạt động bình thường, bạn cần đảm bảo rằng View Controller B đang nhận các sự kiện hệ thống (đọc lệnh gọi lại UIViewControllerDelegate). 'addChildViewController' giải quyết vấn đề này cho bạn, để giúp bạn tiết kiệm công sức chuyển mọi thứ theo cách thủ công.
Sam Clewlow
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.