Ios iPhone11 Pro Max上出现故障内容的UIScrollView

Ios iPhone11 Pro Max上出现故障内容的UIScrollView,ios,swift,swift3,Ios,Swift,Swift3,我是Swift新手,我尝试制作显示视图控制器的UIScrollView 在iPhone 11 Pro Max上,每件事都很完美。下一个屏幕会显示一点侧面: 我的代码: //MARK: - outlets @IBOutlet weak var pageControl: UIPageControl! @IBOutlet weak var scrollView: UIScrollView! //MARK: - properties var viewControllers: [String] =

我是Swift新手,我尝试制作显示视图控制器的
UIScrollView

在iPhone 11 Pro Max上,每件事都很完美。下一个屏幕会显示一点侧面:

我的代码:

//MARK: - outlets

@IBOutlet weak var pageControl: UIPageControl!
@IBOutlet weak var scrollView: UIScrollView!

//MARK: - properties

var viewControllers: [String] = ["ComputerViewController", "AttactViewController", "DefenceViewController", "OfflineViewController"]
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)

//MARK: - life cyrcles
override func viewDidLoad() {
    super.viewDidLoad()


    for index in 0..<viewControllers.count {
        frame.origin.x = scrollView.frame.size.width * CGFloat(index)

        frame.size = scrollView.frame.size


        let view = UIView(frame: frame)

        let storyboard = UIStoryboard(name: "Menu", bundle: nil)
        var controller: UIViewController = storyboard.instantiateViewController(withIdentifier: viewControllers[index]) as UIViewController

        view.addSubview(controller.view)


        self.scrollView.addSubview(view)

    }

    scrollView.contentSize = CGSize(width: scrollView.frame.size.width * CGFloat(viewControllers.count), height: scrollView.frame.size.height)

    scrollView.delegate = self

}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    var pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width

    pageControl.currentPage = Int(pageNumber)
}
//标记:-出口
@IBVAR弱页面控制:UIPageControl!
@iBCROLLVIEW:UIScrollView!
//标记:-属性
var viewControllers:[字符串]=[“ComputerViewController”、“AttachtViewController”、“Defense ViewController”、“OfflineViewController”]
var frame=CGRect(x:0,y:0,宽度:0,高度:0)
//马克:生命圈
重写func viewDidLoad(){
super.viewDidLoad()

对于指数为0..的几项观察结果:

  • 您应该避免在
    viewDidLoad
    中引用
    frame
    。此时,
    frame
    是未知的

  • 您应该完全避免对子视图的大小和位置进行硬编码。以后可能会有各种事件更改视图的大小(例如旋转、拆分视图多任务处理等)。请使用约束

  • 对于滚动视图,有两个布局参考线,一个用于其
    frame
    ,另一个用于其
    contentSize
    。因此,请使用
    frameLayoutGuide
    设置子视图的大小,以及这些子视图相对于
    contentLayoutGuide
    的位置

  • 将视图控制器的
    视图
    添加为子视图时,请确保调用
    addChild(:)
    didMove(toParent:)
    调用视图控制器包含。请参阅中的“实现容器视图控制器”部分

  • 如果要添加分页行为,只需设置滚动视图的
    isPaginEnabled

  • 总而言之:

    override func viewDidLoad() {
        super.viewDidLoad()
        addChildViews()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        var anchor = scrollView.contentLayoutGuide.leadingAnchor
    
        for identifier in viewControllers {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let child = storyboard.instantiateViewController(withIdentifier: identifier)
            addChild(child)                   // containment call
            child.view.translatesAutoresizingMaskIntoConstraints = false
            scrollView.addSubview(child.view)
            child.didMove(toParent: self)     // containment call
    
            NSLayoutConstraint.activate([
                // define size of child view (relative to `frameLayoutGuide`)
    
                child.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
                child.view.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),
    
                // define placement of child view (relative to `contentLayoutGuide`)
    
                child.view.leadingAnchor.constraint(equalTo: anchor),
                child.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
                child.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
            ])
    
            anchor = child.view.trailingAnchor
        }
        anchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true
        scrollView.isPagingEnabled = true
    }
    
    我已经删除了属性
    frame
    ,因为不再需要它了(这只是与视图控制器的同名视图属性混淆的一个原因)。我还删除了容器视图,因为它没有给整个解决方案添加太多内容(只添加了一层要添加的约束)


    但关键是使用约束来指定滚动视图中子视图的大小和位置,并使用视图控制器包含API。

    两个观察结果:

  • 您应该避免在
    viewDidLoad
    中引用
    frame
    。此时,
    frame
    是未知的

  • 您应该完全避免对子视图的大小和位置进行硬编码。以后可能会有各种事件更改视图的大小(例如旋转、拆分视图多任务处理等)。请使用约束

  • 对于滚动视图,有两个布局参考线,一个用于其
    frame
    ,另一个用于其
    contentSize
    。因此,请使用
    frameLayoutGuide
    设置子视图的大小,以及这些子视图相对于
    contentLayoutGuide
    的位置

  • 将视图控制器的
    视图
    添加为子视图时,请确保调用
    addChild(:)
    didMove(toParent:)
    调用视图控制器包含。请参阅中的“实现容器视图控制器”部分

  • 如果要添加分页行为,只需设置滚动视图的
    isPaginEnabled

  • 总而言之:

    override func viewDidLoad() {
        super.viewDidLoad()
        addChildViews()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        var anchor = scrollView.contentLayoutGuide.leadingAnchor
    
        for identifier in viewControllers {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let child = storyboard.instantiateViewController(withIdentifier: identifier)
            addChild(child)                   // containment call
            child.view.translatesAutoresizingMaskIntoConstraints = false
            scrollView.addSubview(child.view)
            child.didMove(toParent: self)     // containment call
    
            NSLayoutConstraint.activate([
                // define size of child view (relative to `frameLayoutGuide`)
    
                child.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
                child.view.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),
    
                // define placement of child view (relative to `contentLayoutGuide`)
    
                child.view.leadingAnchor.constraint(equalTo: anchor),
                child.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
                child.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
            ])
    
            anchor = child.view.trailingAnchor
        }
        anchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true
        scrollView.isPagingEnabled = true
    }
    
    我已经删除了属性
    frame
    ,因为不再需要它了(这只是与视图控制器的同名视图属性混淆的一个原因)。我还删除了容器视图,因为它没有给整个解决方案添加太多内容(只添加了一层要添加的约束)


    但关键是使用约束来指定滚动视图中子视图的大小和位置,并使用视图控制器包含API。

    这种方法会有几个问题……但是首先,您是否考虑过使用
    UIPageViewController
    ?它内置了所有这些功能。您将有几个问题ms采用这种方法…但首先,您是否考虑过使用
    UIPageViewController
    ?它内置了所有这些功能。首先,非常感谢您的帮助,它解决了问题,但现在有了新问题:他缩小了我的视图高度。之前:之后:THANKS@LiorD-看起来您还没有定义垂直约束甚至滚动视图及其超级视图(例如滚动视图的底部及其下方的任何内容)。但这与上面的代码无关,该代码假定您已定义了滚动视图的高度,并且只担心在该滚动视图中配置子视图/页面。首先,非常感谢您的帮助,它解决了问题,但现在有一个新问题:他缩小了我的视图高度。之前:之后:THANKS@LiorD-它看起来像是一只猫您尚未定义滚动视图与其超级视图之间的垂直约束(例如滚动视图的底部及其下方的任何内容)。但这与上面的代码无关,上面的代码假定您已定义了滚动视图的高度,并且只担心配置该滚动视图内的子视图/页面。