2013-06-19 35 views
83

Tôi chỉ mới nhúng chân vào 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 custom container view controller - cho phép gọi nó là SideBarViewController - hoán đổi một số bộ điều khiển có thể xem con hiển thị, gần như chính xác giống như Bộ điều khiển Thanh tab tiêu chuẩn. (Đó là khá nhiều Tab Bar khiển nhưng với một menu bên hideable thay vì một thanh tab.)addChildViewController thực sự làm gì?

Theo các hướng dẫn trong tài liệu hướng dẫn của Apple, tôi gọi addChildViewController bất cứ khi nào tôi thêm một đứa trẻ ViewController để container của tôi. Mã của tôi để bơm nạp tiếp ra bộ điều khiển xem con hiện tại được hiển thị bởi các SideBarViewController trông như thế này:

- (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 chỉ là những gì addChildViewController làm ở đây, và tôi nhận ra rằng tôi không có ý tưởng. Bên cạnh việc gắn bó mới ViewController trong mảng .childViewControllers, có vẻ như không ảnh hưởng đến bất kỳ thứ gì. Các hành động và cửa hàng từ giao diện điều khiển con cho bộ điều khiển con 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 addChildViewController và tôi không thể tưởng tượng điều gì khác có thể ảnh hưởng.

Thật vậy, nếu tôi viết lại mã của tôi để không gọi addChildViewController, và 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; 
} 

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

Tài liệu của Apple không làm sáng tỏ những gì addChildViewController làm hoặc tại sao chúng tôi phải gọi nó. Toàn bộ phạm vi của mô tả có liên quan về phương pháp hoặc tại sao nó nên được sử dụng trong phần của nó trong UIViewController Class Reference là, hiện tại:

Thêm bộ điều khiển xem đã cho. ... Phương pháp 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 siêu trong triển khai của mình.

Ngoài ra còn có đoạn này trước đó trên cùng một trang:

view controller chứa của bạn phải kết hợp một bộ điều khiển xem đứa trẻ với bản thân trước khi thêm xem gốc của đứa trẻ để hệ thống phân cấp xem. Điều này cho phép iOS định tuyến đúng sự kiện cho bộ điều khiển chế độ xem con và chế độ xem mà các trình điều khiển quản lý. Tương tự, sau khi loại bỏ chế độ xem gốc của con từ cấu trúc phân cấp của chế độ xem, nó sẽ tự ngắt kết nối với trình điều khiển chế độ xem con đó. Để 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 có ý định được gọi bởi các máy khách của lớp container của bạn; chúng chỉ được sử dụng bởi việc triển khai vùng chứa của bạn để cung cấp hành vi ngăn chặn dự kiến.

Sau đây là các phương pháp cần thiết bạn có thể cần phải gọi:

addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:

nhưng nó không cung cấp bất kỳ đầu mối như những gì 'sự kiện' hoặc 'hành vi ngăn chặn dự kiến' mà nó đang nói đến là, hoặc tại sao (hoặc ngay cả khi) gọi những phương pháp này là 'thiết yếu'. Các ví dụ về bộ điều khiển chế độ xem thùng chứa tùy chỉnh trong phần "Bộ điều khiển chế độ xem bộ chứa tùy chỉnh" của tài liệu Apple đều gọi phương pháp 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 bật ViewController con lên một mảng, nhưng tôi không thể tìm ra mục đích đó là gì. Phương pháp này làm gì và tại sao tôi nên gọi nó?

+3

của Apple [** 2011 ** WWDC] (https://developer.apple.com/videos/wwdc/2011/) trang video có phiên _great_ ("Triển khai Ngăn chứa UIViewController") về chủ đề này. – Alladinian

Trả lời

81

Tôi cũng đã tự hỏi về câu hỏi này. Tôi đã xem Session 102 of the WWDC 2011 video và Ông View Controller, Bruce D. Nilo, nói điều này:

viewWillAppear:, viewDidAppear:, vv không có gì để làm với addChildViewController:. Tất cả những gì addChildViewController: làm là để nói "Bộ điều khiển xem này là một đứa trẻ của điều đó" và nó không có gì để làm với sự xuất hiện xem. Khi họ nhận được gọi được liên kết với khi quan điểm 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ư cuộc gọi tới addChildViewController: rất ít. Các tác dụng phụ của cuộc gọi là một phần quan trọng. Chúng đến từ các mối quan hệ parentViewControllerchildViewControllers. Dưới đây là một số tác dụng phụ mà tôi biết:

  • phương pháp Forwarding xuất hiện để xem các bộ điều khiển con
  • Forwarding phương pháp luân chuyển
  • cảnh báo
  • (Có thể) bộ nhớ chuyển tiếp
  • Tránh phân cấp VC không phù hợp, đặc biệt là trong transitionFromViewController:toViewController:… trong đó cả hai VC cần phải có cùng một phụ huynh
  • Cho phép bộ điều khiển chế độ xem vùng chứa tùy chỉnh tham gia vào Bảo tồn và phục hồi của tiểu bang
  • T aking phần trong chuỗi responder
  • Hooking lên navigationController, tabBarController, vv thuộc tính
+0

Phiên này 102 không 101 – SeanChense

+0

+1 cho chuỗi phản hồi. addChildViewController là bắt buộc nếu bạn muốn nhận sự kiện chạm trên một chế độ xem con thuộc sở hữu của một UIViewController con – charlieb

9

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

Trước đây, để giữ tham chiếu của chế độ xem khácBộ điều khiển mà bạn đã sử dụng chế độ xem, bạn phải giữ tham chiếu thủ công của chúng trong @properties. Có một thuộc tính dựng sẵn như childViewControllers và do đó parentViewController là 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 chế độ xem được sắp xếpBộ điều khiển 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, vv Trước đây bạn nên gọi phương thức này theo cách thủ công trên "childrenViewControllers" của bạn.

Vậy đó.

+0

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à trẻ nhận được không? Tìm kiếm trên Google cho các sự kiện hệ thống của "iOS" "không phát sinh nhiều; nó không có vẻ là một thuật ngữ mà Apple sử dụng? –

+0

Về cơ bản nó là một phương thức tiện lợi cho phép bạn thêm khung nhìn View Controller B như là một khung nhìn con của View Controller A, nhưng vẫn có View Controller B quản lý khung nhìn của nó. Để điều này hoạt động đúng, bạn cần đảm bảo rằng View Controller B đang nhận được các sự kiện hệ thống (đọc UIViewControllerDelegate callbacks). 'addChildViewController' móc điều này cho bạn, để giúp bạn tiết kiệm công sức của việc truyền tải mọi thứ theo cách thủ công. –

94

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

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

enter image description here

Sau khi thử một số giải pháp, tôi đã kết thúc phát minh ra giải pháp tùy chỉnh của riêng tôi để hiển thị các notepad. Vì vậy, khi tôi muốn hiển thị notepad, tôi tạo một thể hiện mới là NotepadViewController và 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.

enter image description here

Vì vậy, tôi muốn thay đổi hình ảnh notepad và dịch chuyển lên. Và để làm như vậy, tôi đã viết mã thích hợp trong phương pháp willAnimateRotationToInterfaceOrientation:duration:, nhưng khi tôi chạy ứng dụng không có gì xảy ra! Và sau khi gỡ lỗi, tôi nhận thấy rằng không có phương pháp xoay nào của UIViewController thực sự được gọi là trong NotepadViewController. Chỉ những phương thức trong bộ điều khiển xem chính mới đượ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 theo cách 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 thêm sự phụ thuộc 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 về bộ điều khiển chế độ xem con được giới thiệu. Nhưng bây giờ, bạn chỉ cần addChildViewController đến bộ điều khiển chế độ xem chính và mọi thứ sẽ hoạt động như mong đợi mà không cần bất kỳ công việc thủ công nào khác.

Edit: Có hai loại sự kiện được chuyển tiếp đến xem con điều khiển:

1- Phương pháp Hình thức:

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

2- Phương pháp Rotation:

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

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

+0

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

+0

muốn tự động chuyển tiếp chế độ xemWillLayoutSubviews – MobileMon

Các vấn đề liên quan