xcode 是否可以使用代码在滚动视图中嵌入 segue/包含视图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18928732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 03:51:23  来源:igfitidea点击:

Is it possible to have embed segue/containing view in a scrollview with code?

iosobjective-cxcodecontainers

提问by huggie

On an iPhone project I'm using Xcode storyboard to embed a few containing views in a main scroll view. I've heard containing view is also an "embed segue". Now I don't necessarily have to embed other child controllers, I could have just created custom views and have the original child controllers' logic in those custom subviews. (I think I'm just going to do that after posting here, because it seems easier.) But I've already done the code and want to know how easy or hard it is to stay with it.

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

Because scroll view content is greater than the main screen bounds, it's harder to layout the container view in storyboard. I can think of three ways to solve it. I can either

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

  1. Drag the scroll view up and down and put my container views there.
  2. Just drag some view in the scroll view, and then resize the frame in the main controller's viewDidLoad. (And if I'm using auto layout then I would add auto layout there) But just seems to defy the advantage of having storyboard and embed segue in the first place. But it seems easier than #3 if I have to interact with child view controllers.
  3. Forget storyboard and just write a Containing controller logic (as described in WWDC 2012 video Implementing UIViewController Containment) but this appears to be complicated.
  1. 上下拖动滚动视图并将我的容器视图放在那里。
  2. 只需在滚动视图中拖动一些视图,然后在主控制器的 viewDidLoad 中调整框架的大小。(如果我使用自动布局,那么我会在那里添加自动布局)但似乎无视故事板和嵌入 segue 的优势。但是如果我必须与子视图控制器交互,它似乎比 #3 更容易。
  3. 忘记故事板,只需编写一个包含控制器逻辑(如 WWDC 2012 视频实现 UIViewController Containment 中所述),但这似乎很复杂。

Is there a way to create embed segue in Xcode, but NOT putting it in but to do something like a "manual segue" as with other view transitions? I wouldn't be able to see the layout in storyboard but at least it'll be easier than #3 and I don't have to drag up and down like #2 which seems silly.

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

回答by Firo

I understand that the WWDC has an hour of video on it. But if you have watched any of their other videos it should become quite clear that time does not directly relate to complexity. This is how you use a container (or a child sub view controller) programmatically:

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

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

Pretty simple and only two extra lines of code compared to adding a subview. As you said, there are storyboard solutions but depending on your complexity, doing this through code may be easier. It really comes down to your preference though.

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

If you intend to animate adding the view, you should make the last call to didMoveToParentViewControllerin the completion block (i.e. after the animation has been completed).

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

回答by Evgenii

Here are the helper functions I use to programmatically embed a child view controller in a view.

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

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
  }
}

Usage:

用法:

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

Where:

在哪里:

  • "MyViewControllerId"- the storyboard ID of the child view controller that will be embedded.
  • "MyStoryboardName"- the name of the storyboard file with embedded view controller.
  • containerView- the view in your container view controller that will have the child view controller embedded.
  • “MyViewControllerId”- 将被嵌入的子视图控制器的故事板 ID。
  • “MyStoryboardName”- 带有嵌入式视图控制器的故事板文件的名称。
  • containerView- 将嵌入子视图控制器的容器视图控制器中的视图。