是否可以在包含代码的scrollview中嵌入segue / contains视图?

时间:2013-09-21 03:58:50

标签: ios objective-c xcode containers

在iPhone项目中,我正在使用Xcode故事板在主滚动视图中嵌入一些包含视图的内容。我听说包含视图也是一个“嵌入segue”。现在我不一定要嵌入其他子控制器,我本可以创建自定义视图并在这些自定义子视图中使用原始子控制器的逻辑。 (我想在发布之后我就会这样做,因为它看起来更容易。)但我已经完成了代码,并且想知道保持它的难易程度。

由于滚动视图内容大于主屏幕边界,因此在故事板中布置容器视图更加困难。我可以想到三种方法来解决它。我可以

  1. 向上和向下拖动滚动视图并将容器视图放在那里。
  2. 只需在滚动视图中拖动一些视图,然后在主控制器的viewDidLoad中调整框架的大小。 (如果我正在使用自动布局,那么我会在那里添加自动布局)但似乎只是违背了故事板和嵌入segue的优势。但如果我必须与子视图控制器交互,它似乎比#3更容易。
  3. 忘记故事板并编写一个包含控制器逻辑(如WWDC 2012视频实现UIViewController Containment中所述),但这看起来很复杂。
  4. 有没有办法在Xcode中创建嵌入segue,但是没有把它放进去,而是像其他视图过渡一样做“手动segue”之类的东西?我无法在故事板中看到布局,但至少它比#3更容易,我不必像#2那样上下拖动,这似乎很傻。

2 个答案:

答案 0 :(得分:30)

据我所知,WWDC上有一小时的视频。但是如果你看过他们的任何其他视频,那么时间就不应该与复杂性直接相关了。这是以编程方式使用容器(或子子视图控制器)的方式:

[self addChildViewController:child];        // 1
[self.view addSubview:child.view];          // 2
[child didMoveToParentViewController:self]; // 3

与添加子视图相比,非常简单,只有两行代码。正如您所说,有故事板解决方案,但根据您的复杂性,通过代码执行此操作可能会更容易。这真的取决于你的偏好。

如果您想要添加视图的动画,则应在完成块中对didMoveToParentViewController进行最后一次调用(即动画完成后)。

答案 1 :(得分:1)

以下是我用于在视图中以编程方式嵌入子视图控制器的辅助函数。

struct MyChildViewController {
  static func embed(
    viewControllerId: String,
    storyboardName: String,
    containerViewController: UIViewController,
    containerView: UIView) -> UIViewController? {

    guard let viewController = initViewController(viewControllerId, storyboardName: storyboardName)
      else { return nil }

    containerViewController.addChildViewController(viewController)
    containerView.addSubview(viewController.view)

    viewController.view.translatesAutoresizingMaskIntoConstraints = false

    MyConstraints.fillParent(
      viewController.view, parentView: containerView, margin: 0, vertically: true)

    MyConstraints.fillParent(
      viewController.view, parentView: containerView, margin: 0, vertically: false)

    viewController.didMoveToParentViewController(containerViewController)

    return viewController
  }

  static func initViewController(viewControllerId: String, storyboardName: String) -> UIViewController? {
    let storyboard = UIStoryboard(name: storyboardName, bundle: NSBundle.mainBundle())
    return storyboard.instantiateViewControllerWithIdentifier(viewControllerId)
  }
}

struct MyConstraints {
  static func fillParent(view: UIView, parentView: UIView, margin: CGFloat = 0,
    vertically: Bool) -> [NSLayoutConstraint] {

    var marginFormat = ""

    if margin != 0 {
      marginFormat = "-\(margin)-"
    }

    var format = "|\(marginFormat)[view]\(marginFormat)|"

    if vertically {
      format = "V:" + format
    }

    let constraints = NSLayoutConstraint.constraintsWithVisualFormat(format,
      options: [], metrics: nil,
      views: ["view": view])

    parentView.addConstraints(constraints)

    return constraints
  }
}

用法:

let childWiewController = MyChildViewController.embed("MyViewControllerId", storyboardName: "MyStoryboardName", containerViewController: containerViewController, containerView: containerView)

其中:

  • " MyViewControllerId" - 将嵌入的子视图控制器的故事板ID。
  • " MyStoryboardName" - 具有嵌入式视图控制器的情节提要文件的名称。
  • containerView - 容器视图控制器中将嵌入子视图控制器的视图。