2013-08-23 25 views
36

Có cách nào để có một ContainerView đơn lẻ với nhiều phân đoạn được nhúng không? Mục đích là cho một ContainerView để giữ một vài ViewControllers khác nhau tùy thuộc vào các nút đã được nhấn; chỉ có một người sẽ được hiển thị cùng một lúc. Tôi muốn sử dụng các phân đoạn nhúng để trong Interface Builder, các bảng phân cảnh được tự động hiển thị ở cùng kích thước với ContainerView.ContainerView với nhiều phân đoạn nhúng

Tôi nhận ra rằng tôi có thể tự thay đổi kích thước các ViewControllers khác trong InterfaceBuilder, nhưng tôi muốn kích thước tự động được cung cấp bởi segue nhúng. Nếu một cách khác để làm điều đó có sẵn, điều đó cũng sẽ ổn. Không có lượt xem trên viewDidLoad là tốt - như đã đề cập trước đó, ViewController hiển thị có thể thay đổi tùy thuộc vào các nút được nhấn.

+1

Tôi nhận ra đây không phải là những gì bạn hỏi, nhưng như cách giải quyết khác, làm thế nào về việc có nhiều ContainerViews, chồng chéo và kích thước giống hệt nhau, mỗi segue tùy chỉnh riêng của họ. Sau đó, trong mã, thực hiện các segue chính xác bằng cách sử dụng '[self performSegueWithIdentifier:]' tùy thuộc vào con UIViewController bạn muốn hiển thị. Ít nhất, theo cách này, bạn giữ cho kích thước tự động của bạn, bạn giữ cho các kết nối của bạn trong IB và bạn giữ logic 'preparForSegue' của bạn. –

Trả lời

38

Không, không có cách nào để có nhiều phân đoạn nhúng vào một chế độ xem vùng chứa. Một cách để làm tất cả các thiết lập trong IB, sẽ là làm cho bộ điều khiển nhúng một UITabBarController (với thanh tab ẩn). Sau đó bạn có thể có nhiều bộ điều khiển trong các tab như bạn muốn, và chuyển sang chúng trong mã bằng cách sử dụng thuộc tính selectedIndex của UITabBarController.

+0

Tôi nhìn xung quanh một chút trước khi hỏi, nhưng tôi cho rằng tôi cứ hy vọng tôi sẽ bỏ lỡ một cái gì đó. Ồ, tôi sẽ chỉ sống với những quan điểm sai kích thước. (Ý tưởng của bạn về việc sử dụng TabBarController là thú vị, nhưng tiếc là ContainerView của tôi đã là một TabBarController khác). –

+9

Tôi nhận ra đây là câu trả lời cũ. Cách tôi giải quyết điều này, mà không thực sự suy nghĩ nhiều về nó là có nhiều container xem và chỉ có một cái nhìn thấy tại thời điểm đó. Không biết nếu đó là cách tốt nhất, nhưng nó hoạt động tốt. –

+0

Người trả lời tuyệt vời. Vẫn là một giải pháp tốt. – DevZarak

14

Tôi nhận ra câu hỏi này hơi cũ, nhưng tôi muốn trả lời trong trường hợp bạn vẫn đang tìm kiếm hoặc những người khác tìm thấy câu hỏi này. Tôi đã có một vấn đề tương tự và tôi đã làm việc xung quanh nó.

Nói tóm lại, bạn sẽ có ba lớp:
- một bộ điều khiển cách nhìn khách quan ("ExternalViewController")
- một người quản lý xem điều khiển ("ViewControllerManager")
- quan điểm con điều khiển bạn thực sự muốn trở thành chuyển đổi giữa ("ChildViewController")

Sử dụng chế độ xem vùng chứa trong ExternalViewController với phân đoạn nhúng vào ViewControllerManager. Chính ViewControllerManager sau đó sẽ giữ các ChildViewControllers khác theo chương trình như được mô tả in this Apple documentation, cụ thể là phần thêm và xóa một đứa trẻ.

Khi bạn thêm bộ điều khiển chế độ xem con, hãy đặt khung của nó giống với khung của ViewControllerManager (vì bạn đang làm điều này bên trong ViewControllerManager, đặt khung của con bằng self.view.frame). Bạn cũng sẽ cần một số logic và một điều khiển bên ngoài để làm việc chuyển đổi bên trong của ExternalViewController, tất nhiên.

Hy vọng điều này sẽ hữu ích!

2

Tôi đã đạt được điều đó bằng cách sử dụng -shouldPerformSegueWithIdentifier:sender:. Tôi có một container được thông qua một đối tượng và tùy thuộc vào loại đối tượng này quyết định bộ điều khiển xem con nào sẽ hiển thị.

Cấu trúc có vẻ phức tạp hơn một chút nhưng cho phép trình điều khiển chế độ xem cơ sở bỏ qua các loại nhiệm vụ khác nhau mà tôi có, để lại cho bộ điều khiển xem bộ chứa. Bộ điều khiển xem bộ chứa sau đó có nhiều chế độ xem vùng chứa mà phân đoạn chỉ được thực hiện tùy thuộc vào loại tác vụ.

Tôi không biết liệu bạn có thể thực sự thực hiện phân đoạn nhúng theo cách thủ công hay không bằng cách gọi -performSegueWithIdentifier:sender: nhưng đó cũng có thể là một khả năng.

17

tôi tìm thấy bài viết tuyệt vời này mà giải thích một cách chính xác làm thế nào để làm điều đó: http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers

bạn nhận container của bạn và có thể gọi bất kỳ điều khiển xem đằng sau, có một chút thiết lập để có tất cả mọi thứ liên quan nhưng khi thực hiện, bạn có một bảng phân cảnh có thể sử dụng được.

+0

Câu trả lời này có nó có thể theo liên kết – Feras

+0

Điều này làm việc tốt hơn cho tôi. Nhược điểm chính của bộ điều khiển xem tab là VC của mỗi tab tiếp tục tồn tại khi không nhìn thấy được. Khi chúng không hiển thị, tôi muốn nó deinit và sau đó reinitialize từ đầu nếu nó cần phải quay trở lại. –

+0

Liên kết không hoạt động với tôi –

11

Có, tôi đã có thể đạt được những gì bạn đang tìm kiếm lấy cảm hứng từ bài đăng @rdelmar. Những gì bạn cần làm là nhúng UITabBarViewController vào chế độ xem vùng chứa của bạn. Sau đó, bạn lập trình chọn bộ điều khiển bạn muốn trình bày. Bạn cũng có thể muốn ẩn thanh tab.

Container view indirectly containing more views

Nếu bạn muốn, bạn cũng có thể ẩn các thanh tab thấy trong file storyboard

Bạn có thể chọn bộ điều khiển xem bạn muốn trình bày bởi subclassing UITabBarController:

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.selectedIndex = 1 
} 

Bạn có thể ẩn thanh tab trong bộ điều khiển chế độ xem của mình bằng cách gọi self.tabBarController?.tabBar.hidden = true trong chế độ xemDidLoad().

+0

Điều này hữu ích, nhưng làm cách nào để chọn một mục từ VC chính của tôi (Có chứa ContainerView)? Tôi đã thử đặt 'self.tabBarController? .selectedIndex = 5' trong' viewDidLoad() 'nhưng nó không hoạt động): – user5195185

+2

Bạn làm điều đó trong phương thức 'preparForSegue'. Một cái gì đó như thế này: 'bảo vệ cho tabBarVC = segue.destination như? UITabBarController else {return} 'và sau đó' tabBarVC.selectedIndex = 5 '. Có lẽ tôi đã thực hiện một số lỗi kể từ khi tôi đang gõ trên điện thoại, nhưng hy vọng ý tưởng là rõ ràng. – Andrej

+0

Cảm ơn, bro! Giúp tôi. – user5195185

0

Tôi đã vật lộn với điều này trong một thời gian dài. Tôi đã có trường hợp mà tôi đã khác nhau, nhưng tương tự nhúng bảng điều khiển xem mà tôi muốn hiển thị tùy thuộc vào một tham số được thiết lập trong segue để xem bộ điều khiển. Những gì đã làm việc được đưa vào container nhúng với một IBOutlet trong bộ điều khiển khung nhìn. Vùng chứa có thể có các ràng buộc về kích thước được đặt trong IB. Tuy nhiên, không thực hiện bất kỳ phân đoạn nhúng nào trong IB. Sau đó, trong viewDidLoad, tôi lập trình thêm bộ điều khiển xem chính xác và ghim các cạnh của nó vào vùng chứa nhúng.

Trái tim của phương pháp này được nhìn thấy trong đoạn mã sau (Swift 4):

extension UIView { 
    func pinToParent() { 
     self.translatesAutoresizingMaskIntoConstraints = false 
     let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left] 
     NSLayoutConstraint.activate(attributes.map { 
      NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0) 
     }) 
    } 
} 

class ColorVC: UIViewController { 

    @IBOutlet weak var tableContainer: UIView! 
    var color : rgb = .red 

    fileprivate var colorTableVC : ColorTableVC? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     switch color { 
     case .red: 
      colorTableVC = RedTableVC.init(style: .plain) 
     case .green: 
      colorTableVC = GreenTableVC.init(style: .plain) 
     case .blue: 
      colorTableVC = BlueTableVC.init(style: .plain) 
     } 
     if let vc = colorTableVC { 
      if (vc.view) != nil { 
       self.addChildViewController(vc) 
       tableContainer.addSubview(vc.view) 
       vc.view.pinToParent() 
       vc.didMove(toParentViewController: self) 
      } 
     } 
    } 
} 

Trong ColorVC, người ta thấy các IBOutlet container và "màu sắc" tham số được thiết lập bởi bộ điều khiển xem bảng chính. RedTableVC, GreenTableVC và BlueTableVC đều được phân lớp từ ColorTableVC được phân loại phụ từ UITableViewController. Di sản chung cho phép tôi sử dụng một biến "colorTableVC" để trỏ đến bất kỳ bộ điều khiển tức thời nào. (Không hoàn toàn cần thiết). Nhưng điều này không tránh trùng lặp mã bên dưới để thêm chế độ xem trong chế độ thừa kế và ghim bộ điều khiển mới vào chế độ xem vùng chứa. Ở trên cùng, tôi đã tạo một tiện ích mở rộng trên UIView để ghim chế độ xem cho cạnh mẹ của nó.

Hình ảnh sau đây cho thấy cách dự án và đặc biệt là bộ điều khiển chế độ xem bên phải được thiết lập trong IB. Đối với ví dụ này, tôi đã tạo chiều cao của bộ điều khiển "nhúng" một nửa chiều cao của bộ điều khiển xem chính - vì vậy khi bạn xoay thiết bị, người ta có thể thấy rằng các ràng buộc được đặt trong IB thực sự được áp dụng.

Embedded controller IB setup

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