【问题标题】:Add child view controller swift快速添加子视图控制器
【发布时间】:2014-08-20 12:16:45
【问题描述】:

我正在尝试将子视图控制器添加到 containerViewController

孩子是:

AViewController
BViewController
CViewController

我没有错误,但是当我启动应用程序时,我可以滑动屏幕,滑动了 3 个部分但 A、B、C 视图控制器没有出现..

这是我的代码,你知道吗?

import UIKit

class ContainerViewController: UIViewController {

@IBOutlet var scrollView: UIScrollView!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


    // creat VC

    var Avc : AViewController = AViewController ()
    var Bvc : BViewController = BViewController ()
    var Cvc : CViewController = CViewController ()



    // add it to the view hierarchie


    self.addChildViewController(Cvc)
    self.scrollView.addSubview(Cvc.view)
    Cvc.didMoveToParentViewController(self)

    self.addChildViewController(Bvc)
    self.scrollView.addSubview(Bvc.view)
    Bvc.didMoveToParentViewController(self)


    self.addChildViewController(Avc)
    self.scrollView.addSubview(Avc.view)
    Avc.didMoveToParentViewController(self)

    // set the frame

    var adminFrame : CGRect = Avc.view.frame
    adminFrame.origin.x = adminFrame.width
    Bvc.view.frame = adminFrame

    var BFrame : CGRect = Bvc.view.frame
    BFrame.origin.x = 2*BFrame.width
    Cvc.view.frame = BFrame

    // set the frame of the scrollview


    var scrollWidth: CGFloat = 3*self.view.frame.width
    var scrollHeight: CGFloat = self.view.frame.size.height
    self.scrollView.contentSize = CGSizeMake(scrollWidth, scrollHeight)


}

编辑:

查看视图层次结构,它报告以下内容:

<UIWindow: 0x7ff3fad19f70; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x7ff3fac3efe0>; layer = <UIWindowLayer: 0x7ff3fad19740>>
   | <UIView: 0x7ff3fb108b90; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff3fb108e60>>
   |    | <UIScrollView: 0x7ff3fac3acf0; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7ff3fb107320>; layer = <CALayer: 0x7ff3fac18e00>; contentOffset: {0, 0}; contentSize: {960, 568}>
   |    |    | <UIView: 0x7ff3fac41ed0; frame = (640 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff3fac28a00>>
   |    |    | <UIView: 0x7ff3fac42320; frame = (320 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff3fac38e10>>
   |    |    | <UIView: 0x7ff3fac42730; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff3fac42810>>
   |    |    | <UIImageView: 0x7ff3faf020f0; frame = (0 564.5; 320 3.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x7ff3fae0df80>>
   |    |    | <UIImageView: 0x7ff3fac1c660; frame = (316.5 0; 3.5 568); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x7ff3fac39420>>
   |    | <_UILayoutGuide: 0x7ff3fb108ec0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7ff3fb1091e0>>
   |    | <_UILayoutGuide: 0x7ff3fb109c20; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x7ff3fb109d00>>

【问题讨论】:

  • 您可能想要暂停应用程序并在(lldb) 提示符处输入po [[UIWindow keyWindow] recursiveDescription],这将显示所有视图的框架。在我看来,您从未设置过Avc.view.frame,所以我打赌它是CGRectZero。在你开始设置BvcCvc 的框架之前,我建议Avc.view.frame = self.view.bounds
  • 我认为唯一无法显示的框架是我容器的 scrollView 框架,我尝试了您的解决方案,但它不起作用。
  • (lldb) po [[UIWindow keyWindow] recursiveDescription] ;层 = > | > | |
  • 太棒了!所以你的子视图那里!但是你显然没有在这些子视图中添加任何东西,所以没有什么可看的。
  • 我只是更改了每个颜色的背景以识别不同的子视图,但是在滑动时我看不到不同的颜色,一切都是白色的。我还添加了一个标签...

标签: ios view controller swift


【解决方案1】:

使用以下扩展添加 ChildviewController 创建文件 Extensions.swift 复制下面的代码

import UIKit

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: holderView!, view: childController.view)
        childController.didMove(toParentViewController: 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])
    }
}

用户视图控制器

    import UIKit

    class MyViewControler:UIViewControler  {

    @IBOutlet weak var myView: UIView!



    override func viewDidLoad() {
        super.viewDidLoad()

        let demoViewInstance = storyboard!.instantiateViewController(withIdentifier: "youChiledViewController_Id") as! childViewController
        configureChildViewController(childController: demoViewInstance, onView: myView)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

【讨论】:

  • 我发现你的答案有点不清楚 - 约束来自哪里?您能否澄清一下您的扩展打算做什么以及为什么建议使用这种方法?这将帮助我了解如何处理这个问题。
  • @NataliaChodelski 请检查上面更新的代码以便更好地理解
  • @PhaniSai 我稍微修改了你的代码,所以没有显式解包holderView!gist.github.com/neoneye/fd01d21944b40fc7794af6c8f0591725
【解决方案2】:

当我使用您的代码、运行应用程序、暂停应用程序并查看视图层次结构时,我看到以下内容:

(lldb) po [[UIWindow keyWindow] recursiveDescription]
<UIWindow: 0x156bdc30; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x156be750>; layer = <UIWindowLayer: 0x156aa3c0>>
   | <UIView: 0x156c5440; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x156c55c0>>
   |    | <UIScrollView: 0x156c2740; frame = (0 0; 0 568); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x156c4d00>; layer = <CALayer: 0x156c2a80>; contentOffset: {0, 0}; contentSize: {960, 568}>
   |    |    | <UIView: 0x156c6df0; frame = (640 0; 0 536); autoresize = W+H; layer = <CALayer: 0x156c6d80>>
   |    |    | <UIView: 0x156c7100; frame = (320 0; 0 536); autoresize = W+H; layer = <CALayer: 0x156c70a0>>
   |    |    | <UIView: 0x156c73f0; frame = (0 0; 0 536); autoresize = W+H; layer = <CALayer: 0x156c7390>>
   |    |    | <UIImageView: 0x156c8bd0; frame = (0 564.5; 600 3.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x156c8c50>>
   |    |    | <UIImageView: 0x156c9020; frame = (-3.5 32; 3.5 568); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x156c90a0>>
   |    | <_UILayoutGuide: 0x156c5620; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x156c5800>>
   |    | <_UILayoutGuide: 0x156c5c90; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x156c5d10>>

如果您在那里没有看到您的子视图,那么可能的罪魁祸首包括:

  • 您可能没有在场景中指定视图控制器基类,因此这段代码没有运行。您可以使用println 日志语句或在此viewDidLoad 中的断点来确认这一点,并确保您正在执行此例程。

  • 您可能没有为scrollView 连接@IBOutlet,因此scrollViewnil。通过在viewDidLoad 中放置断点并检查scrollView 属性来确认这一点。


在您修改后的问题中,我们现在可以看到三个子视图存在并且看起来是正确的大小。太好了。

现在的问题是为什么你什么都看不到。如果您将这些定义为情节提要中的场景,您应该:

  • 确保为这三个子场景中的每一个都定义了“基类”和“故事板标识符”;和

  • 当您的主视图控制器实例化三个子视图控制器时,您将使用故事板标识符从故事板中实例化它们(在我的示例中,我分别使用了故事板标识符 ABC ):

    let Avc = storyboard.instantiateViewControllerWithIdentifier("A") as AViewController
    let Bvc = storyboard.instantiateViewControllerWithIdentifier("B") as BViewController
    let Cvc = storyboard.instantiateViewControllerWithIdentifier("C") as CViewController
    

如果您执行上述操作并重复 recursiveDescription,您应该会在输出中看到场景的子视图(例如您添加的标签)。

【讨论】:

  • 那么,当您将断点放在viewDidLoad 中,并在遇到断点时检查scrollView 时,它不是nil
  • 我在这个断点中遇到了错误 po [[UIWindo keyWindow] recursiveDescription] :error: :1:12: error: expected ',' separator [[UIWindow keyWindow] recursiveDescription] ^ , :1:23: 错误:预期的 ',' 分隔符 [[UIWindow keyWindow] recursiveDescription]
  • 对不起,我是菜鸟...我有这个 ;层=;内容偏移:{0, 0};内容大小:{0, 0}>
  • 好的,我尝试从情节提要中实例化,但 ap 崩溃,因为“不包含标识符为 'A' 的视图控制器”。这很正常,因为我无法在情节提要中设置“A”标识符。在我的故事板中,我只有一个视图控制器(ContainerViewControler 类)。 A、B、CViewController 是 xib 文件,因此它们在情节提要中不可见。感谢您的耐心等待,对不起我的英语不好..
  • 使用NIB而不是把它放在你的故事板上很奇怪,但这很好。如果它在 NIB 中,则必须从中实例化视图控制器(例如 let Avc = AViewController(nibName: "nibname", bundle: nil))。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多