9

在一个 iPhone 项目中,我使用 Xcode 故事板在主滚动视图中嵌入了一些包含视图。我听说包含视图也是一种“嵌入转场”。现在我不必嵌入其他子控制器,我可以创建自定义视图并在这些自定义子视图中拥有原始子控制器的逻辑。(我想我只是在发布到这里之后才这样做,因为它看起来更容易。)但是我已经完成了代码并且想知道保持它是多么容易或困难。

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

  1. 上下拖动滚动视图并将我的容器视图放在那里。
  2. 只需在滚动视图中拖动一些视图,然后在主控制器的 viewDidLoad 中调整框架的大小。(如果我使用自动布局,那么我会在那里添加自动布局)但似乎违背了拥有故事板和首先嵌入 segue 的优势。但如果我必须与子视图控制器交互,它似乎比#3 更容易。
  3. 忘记情节提要,只需编写一个包含控制器逻辑(如 WWDC 2012 视频实施 UIViewController Containment 中所述),但这似乎很复杂。

有没有办法在 Xcode 中创建嵌入转场,但不把它放进去,而是像其他视图转换一样做“手动转场”之类的事情?我无法在情节提要中看到布局,但至少它会比 #3 更容易,而且我不必像 #2 那样上下拖动,这看起来很傻。

4

2 回答 2

31

我知道 WWDC 上有一个小时的视频。但是,如果您看过他们的任何其他视频,就会很清楚时间与复杂性没有直接关系。这是您以编程方式使用容器(或子视图控制器)的方式:

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

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

如果您打算动画添加视图,您应该didMoveToParentViewController在完成块中进行最后一次调用(即在动画完成之后)。

于 2013-09-24T13:50:41.157 回答
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 - 容器视图控制器中将嵌入子视图控制器的视图。
于 2015-10-14T22:38:44.853 回答