如何使用Swift在iOS 8中正确添加子视图控制器

7
我已经阅读了文档,但仍然卡在一个困难点上。
我有一个视图控制器对象 C_SelectPhoto。它包含一个容器视图。在容器视图中,我希望子视图控制器 C_SelectPhotoControllerView 能适应其中。它将只是一组照片的数组。但是,设置框架并添加子视图控制器并不起作用。如果我移动所需子视图控制器的 x 值,则不会发生任何效果。
为了弄清楚发生了什么,我对所有内容进行了彩色编码。容器如下,为橙色。根据故事板,容器期望的视图为黄色。我实际想要放置在那里的视图为红色。
以下是故事板: enter image description here 这是我针对 C_SelectPhoto 的控制器代码。
class C_SelectPhoto:Controller
{
    @IBOutlet weak var selectPhotoControllerView: UIView!
    var _collectionViewController:C_SelectPhotoControllerView!

    //TODO PERMISSION IS NEEDED BEFORE FETCHING
    func initController()
    {   
        _collectionViewController = Controller.STORYBOARD.instantiateViewControllerWithIdentifier("selectPhotoControllerView") as C_SelectPhotoControllerView
        displayControllerViewController()
    }

    //show the photo selection
    private func displayControllerViewController()
    {
        addChildViewController(_collectionViewController)
        _collectionViewController.view.frame = CGRectMake(100, 0, 500, 500)
        self.view.addSubview(_collectionViewController.view)
        _collectionViewController.didMoveToParentViewController(self)
    }
}

然而,结果如下所示: enter image description here 首先,黄色类根本不应该被添加,我只想要红色的(UICollectionViewController类)。其次,我可以看出红色类被添加到了错误的位置,因为它的x值根本没有移动。
所以我的问题是: 如何将UIContainerViewController作为子视图控制器添加到主视图控制器C_SelectPhoto中,但是让UIContainerViewController的框架适合我在主视图控制器中的容器?
谢谢!
注意:我正在尝试添加的视图是UICollectionViewControllers。当我添加一个UIViewController时,框架工作得很好,但是当我添加UICollectionViewControllers时,框架不起作用,它们被添加到随机偏移量,并且不考虑我尝试使用框架分配来调整它们的大小。
3个回答

12

已更新至Swift 5+。

在你的视图控制器中只需加入一行代码即可添加子视图控制器。

如果您想要将其添加到任何自定义视图上,则可以使用扩展中的非常可扩展的方法。

 public extension UIViewController {

    /// Adds child view controller to the parent.
    ///
    /// - Parameter child: Child view controller.
    func add(_ child: UIViewController) {
        addChild(child)
        view.addSubview(child.view)
        child.didMove(toParent: self)
    }

    /// It removes the child view controller from the parent.
    func remove() {
        guard parent != nil else {
            return
        }
        willMove(toParent: nil)
        removeFromParent()
        view.removeFromSuperview()
    }
}

如何使用:

添加:在您想要添加子视图控制器的视图控制器中。

// let yourChildViewController = Load fro the storyboard or XIB
add(yourChildViewController)

移除:

yourChildViewController.remove()

看起来是从 https://www.swiftbysundell.com/basics/child-view-controllers/ 直接复制的,没有做任何修改。至少要注明出处。 - Abhinav Mathur
@AbhinavMathur,两种方法非常相似的可能性很大。我看到这篇文章是在我的回答之后于2019年发布的。如果情况是这样的话,给swiftysundell以荣誉也没有什么不好,但我认为这里并不是这种情况。 - Bhuvan Bhatt

12

使用以下扩展在视图上添加子视图控制器

extension UIViewController {   
func configureChildViewController(childController: UIViewController, onView: UIView?) {
    var holderView = self.view
    if let onView = onView {
        holderView = onView
    }
    addChildViewController(childController)
    holderView.addSubview(childController.view)
    constrainViewEqual(holderView, view: childController.view)
    childController.didMoveToParentViewController(self)
    childController.willMoveToParentViewController(self)
}


func constrainViewEqual(holderView: UIView, view: UIView) {
    view.translatesAutoresizingMaskIntoConstraints = false
    //pin 100 points from the top of the super
    let pinTop = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal,
        toItem: holderView, attribute: .Top, multiplier: 1.0, constant: 0)
    let pinBottom = NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal,
        toItem: holderView, attribute: .Bottom, multiplier: 1.0, constant: 0)
    let pinLeft = NSLayoutConstraint(item: view, attribute: .Left, relatedBy: .Equal,
        toItem: holderView, attribute: .Left, multiplier: 1.0, constant: 0)
    let pinRight = NSLayoutConstraint(item: view, attribute: .Right, relatedBy: .Equal,
        toItem: holderView, attribute: .Right, multiplier: 1.0, constant: 0)

    holderView.addConstraints([pinTop, pinBottom, pinLeft, pinRight])
}}

在经历了很多对同一个问题的挫败(具体来说是控制一个UICollectionView的子视图控制器的大小/位置),我偶然发现了这个解决方案。它完美地解决了问题,包括旋转设备时。已点赞。只需要进行一个小的更新:".Top"、".Bottom"、".Left"和".Right"枚举在某个时候已更改为全部小写:".top"、".bottom"、".right"和".left"。 - Tomm P
1
你可以并且应该调用 childController.willMoveToParentViewController(self) - Jordan H
3
两件事情 - 1、addChildViewController(_:)方法会自动调用willMove(toParentViewController:)方法(参考链接:https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html)。2、如果你要调用`willSomething()`和`didSomething()`方法,请确保先调用`willSomething()`方法,再调用`didSomething()`方法。 - iamthearm

5
如果您想让红色控制器成为子控制器,删除黄色控制器,然后从容器向红色控制器进行拖动控制。无需在代码中添加它或进行任何调整大小操作。红色控制器将在Storyboard中设置为与容器相同大小。

我注意到UICollectionView的大小没有遵循我设置的框架。如果我将其框架设置为(0,0,50,50),当我在viewDidAppear中检查其框架时,它的大小为(0,0,768,960)!如果我使用通用的UIViewController,则不会出现此问题。 - Aggressor
@Aggressor,不要设置任何框架。它应该与容器的大小相同,没有任何代码。确保您为容器视图提供所需的约束条件,以便为其提供所需的大小。 - rdelmar
在Storyboard中的控制器底部,我看到了“嵌入式segue到'控制器名称'”。你知道我如何随时添加它们吗?我不小心删除了它,现在似乎无法重新创建。 - Aggressor
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - rdelmar
这个视频描述了因为你让我感到的心情:https://www.youtube.com/watch?v=K4jWvIcL0YU - Aggressor
http://stackoverflow.com/questions/25404484/add-child-view-controller-swift/35473300#35473300 - Phani Sai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接