View Controller Containment hoạt động như thế nào trong iOS 5?


108

Trong WWDC 2011 phiên 102, Apple giới thiệu View Controller Containment, đó là khả năng tạo ra giao diện tùy chỉnh container điều khiển, tương tự UITabBarController, UINavigationControllervà những thứ tương tự.

Tôi đã xem các ví dụ vài lần. Có một loạt các phương pháp liên quan đến mô hình này, nhưng hơi khó để tìm ra chúng một cách chính xác. Tôi sẽ đăng ở đây những gì tôi nghĩ đang diễn ra và xem liệu cộng đồng sẽ xác nhận hay bác bỏ những nghi ngờ của tôi.

Tình huống 1: Chuyển từ không có phụ huynh sang bộ điều khiển chế độ xem chính mới

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Hai dòng đầu tiên phải xảy ra theo thứ tự đã cho, hay chúng có thể bị đảo ngược?

Tình huống 2: Chuyển từ bộ điều khiển chế độ xem chính sang không có bộ điều khiển chế độ xem chính

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

Nó cũng cần thiết để gọi [vc didMoveToParentViewController:nil]? Các ví dụ trong Phần 102 không thực hiện điều này trong trường hợp này, nhưng tôi không biết liệu đó có phải là một thiếu sót hay không.

Tình huống 3: Chuyển từ bộ điều khiển chế độ xem chính này sang bộ điều khiển chế độ xem chính khác

Điều này có thể xảy ra theo cách sau, vì logic trong mỗi bộ điều khiển chế độ xem cha sẽ được đóng gói.

// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];

Câu hỏi

Câu hỏi chính của tôi là: Đây có phải là cách ngăn chặn bộ điều khiển chế độ xem nên hoạt động không? Các cơ học đưa ra ở trên có đúng không?

Có cần phải gọi điện willMoveToParentViewControllertrước khi gọi addChildViewControllerkhông? Điều này có vẻ giống như thứ tự hợp lý đối với tôi, nhưng nó có cần thiết nghiêm ngặt không?

Có cần thiết didMoveToParentViewController:nilsau khi gọi điện removeFromParentViewControllerkhông?

Câu trả lời:


72

Tài UIViewControllerliệu khá rõ ràng về thời điểm và thời điểm không gọi willMove/ didMovecác phương thức. Kiểm tra các "Thực hiện một container View Controller" tài liệu.

Các tài liệu nói rằng nếu bạn không ghi đè addChildViewController, bạn không cần phải gọi willMoveToParentViewController:phương thức. Tuy nhiên, bạn cần gọi didMoveToParentViewController:phương thức sau khi quá trình chuyển đổi hoàn tất. "Tương tự như vậy, bộ điều khiển chế độ xem vùng chứa có trách nhiệm gọi willMoveToParentViewController:phương thức trước khi gọi removeFromParentViewControllerphương thức. removeFromParentViewControllerPhương thức này gọi didMoveToParentViewController:phương thức của bộ điều khiển chế độ xem con."

Ngoài ra, có một ví dụ được làm ở đây và mã mẫu ở đây .

Chúc may mắn


17
Tôi thấy, addChildViewControllernên cân bằng với didMoveToParentViewControllerwillMoveToParentViewControllernên cân bằng với removeFromParentViewController. Điều này thật đúng với gì mà tôi đã tìm kiếm. Không chắc chắn làm thế nào tôi đã bỏ lỡ nó trong tài liệu.
Gregory Higley

Tại sao không? Tại sao bạn không phải gọi willMoveToParentViewController mà lại gọi didMoveToParentViewController?
user4951

Bởi vì đó là những gì tài liệu nói. Apple rõ ràng cảm thấy chúng tôi không cần biết.

7
Lý do là vì hoạt ảnh: Giả sử bạn đang tạo bộ điều khiển điều hướng của riêng mình. Khi bắt đầu hoạt ảnh dạng slide, cần gọi 'willMove' và ở cuối hoạt ảnh, cần gọi 'didMove'. Bây giờ khi bạn gọi 'addChild' ở đầu hoạt ảnh, nó sẽ tự động gọi 'willMove' cho bạn. Nhưng nó không thể biết khi nào hoạt ảnh (nếu có) kết thúc, vì vậy bạn phải gọi 'didMove' theo cách thủ công khi kết thúc hoạt ảnh (hoặc ngay lập tức khi không có hoạt ảnh).
Chris

2
Và đối với hoạt ảnh 'trượt ra', ví dụ như đứa trẻ đang bị xóa, bạn phải gọi 'willMove' theo cách thủ công khi bắt đầu hoạt ảnh, vì nếu không, uikit sẽ không biết khi nào gọi đứa trẻ của bạn là 'viewWillDisappear'. Và ở cuối hoạt ảnh, khi bạn gọi removeFromParentViewController, nó có thể tự động gọi 'didMove' cho bạn.
Chris

23

Phần này không đúng:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Theo tài liệu:

Khi vùng chứa tùy chỉnh của bạn gọi phương thức addChildViewController:, nó sẽ tự động gọi phương thức willMoveToParentViewController: của bộ điều khiển chế độ xem để được thêm vào dưới dạng con trước khi thêm nó.

Vì vậy, bạn không cần [vc willMoveToParentViewController:self]cuộc gọi. Nó được thực hiện tự động khi bạn gọi [self addChildViewController:vc]. Đây là mẫu mã một lần nữa:

[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Để xóa bộ điều khiển chế độ xem:

Phương thức removeFromParentViewController tự động gọi phương thức didMoveToParentViewController: của trình điều khiển chế độ xem con sau khi nó loại bỏ con.

Có lẽ đây là cuộc gọi [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically

Có vẻ như nếu được thực hiện theo cách khác, ngay cả khi nó có vẻ hoạt động, thì PresentationViewController không được đặt trên PresentViewController.
Adrian

Tài liệu cho biết lệnh gọi didMoveToParentViewController " ngay sau khi gọi phương thức addChildViewController:", nó không chỉ định thời điểm bạn thực sự thêm chế độ xem con. Tôi tự hỏi nếu mọi người đã làm điều này sai. Có ví dụ nào trong một số Tài liệu Apple mà chúng tôi có thể kiểm tra điều này không?
Robert

Lưu ý: bạn làm cần phải gọi willMoveToParentViewControllertrước addChildViewControllernếu mục bạn đang di chuyển là một lớp tùy chỉnh với ghi đè addChildViewController(trừ khi ghi đè bạn gọi đó là nội bộ)
bunkerdive
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.