首页 > 解决方案 > 无法将任何子视图添加到 scrollView

问题描述

我感到很困惑。我无法让任何子视图出现在滚动视图中

具体来说,我想添加另一个视图控制器的视图,但我什至不能添加任何标签或任何东西。我也看不到视图调试器层次结构中的任何子视图

我究竟做错了什么??

import UIKit

class MainViewController: UIViewController {

    var scrollView: UIScrollView {
        let scrollView = UIScrollView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
        scrollView.isPagingEnabled = true
        scrollView.backgroundColor = .orange
        scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 3.0, height:  UIScreen.main.bounds.height)
        return scrollView
    }

    var leftViewController: UIViewController {
        let vC = UIViewController()
        vC.view.backgroundColor = .purple
        return vC
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        leftViewController.view.frame = .init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        addChild(leftViewController)
        scrollView.addSubview(leftViewController.view)
        leftViewController.didMove(toParent: self)
    }
}

可以通过自动布局实现我想要的效果,但仍然是硬编码宽度。

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        scrollView.addSubview(scrollViewContainer)
        scrollViewContainer.addArrangedSubview(redView)
        scrollViewContainer.addArrangedSubview(blueView)
        scrollViewContainer.addArrangedSubview(greenView)

        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        scrollViewContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        scrollViewContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        scrollViewContainer.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        scrollViewContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    }

    let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.isPagingEnabled = true
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()

    let scrollViewContainer: UIStackView = {
        let view = UIStackView()
        view.axis = .horizontal
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    let redView: UIView = {
        let view = UIView()
        view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
        view.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height).isActive = true
        view.backgroundColor = .red
        return view
    }()

    let blueView: UIView = {
        let view = UIView()
        view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
        view.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height).isActive = true
        view.backgroundColor = .blue
        return view
    }()

    let greenView: UIView = {
        let view = UIView()
        view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
        view.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height).isActive = true
        view.backgroundColor = .green
        return view
    }()
}

标签: iosarraysuikit

解决方案


如果没有别的,如果您在原始问题中提供的第一个示例,您正在使用计算属性。每次您引用它们时,它们都会返回一个新实例。您应该制作这些存储属性:

var scrollView: UIScrollView = {
    let scrollView = UIScrollView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
    scrollView.isPagingEnabled = true
    scrollView.backgroundColor = .orange
    scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 3.0, height:  UIScreen.main.bounds.height)
    return scrollView
}()

var leftViewController: UIViewController = {
    let vC = UIViewController()
    vC.view.backgroundColor = .purple
    return vC
}()

请注意=()在末尾添加 以指定它们已使用闭包进行初始化。

计算属性的问题在于,因为每个引用都返回一个新实例,所以frame您调整的子视图控制器的视图与您添加为子视图的视图不同。并且您添加孩子的滚动视图与您添加到容器视图控制器的滚动视图不同。


在您修改后的问题中,您使用约束共享代码。如果您使用约束,请确保为所有相关视图设置translatesAutoresizingMaskIntoConstraints为。false否则,它会自动将视图的自动调整大小掩码转换为与您手动添加的新约束冲突的约束。

您还应该尽可能避免constraint(equalToConstant:)使用constraint(equalTo:)、引用主视图。例如:

class ViewController: UIViewController {
    let scrollView: UIScrollView = {
        let view = UIScrollView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.isPagingEnabled = true
        return view
    }()

    let redView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .red
        return view
    }()

    let greenView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .green
        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        scrollView.addSubview(redView)
        scrollView.addSubview(greenView)

        NSLayoutConstraint.activate([
            // set the scroll view to be the size of the main view

            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),

            // set the subviews to be the size of the main view, too

            redView.widthAnchor.constraint(equalTo: view.widthAnchor),
            redView.heightAnchor.constraint(equalTo: view.heightAnchor),

            greenView.widthAnchor.constraint(equalTo: view.widthAnchor),
            greenView.heightAnchor.constraint(equalTo: view.heightAnchor),

            // now dictate where these subviews are in the scroll view vertically ...

            redView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            greenView.topAnchor.constraint(equalTo: scrollView.topAnchor),

            redView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            greenView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            // ... and horizontally

            redView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            greenView.leadingAnchor.constraint(equalTo: redView.trailingAnchor),
            greenView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor)
        ])
    }
}

坦率地说,既然你在谈论全屏子视图控制器,我会完全抛弃这段代码,而只是使用UIPageViewController(这不仅让我们摆脱了调整子视图控制器顶级视图大小的业务,而且让我们做一个更有效的“及时”创建子视图控制器)。

但我想展示如果您手动执行此操作,约束会是什么样子。


推荐阅读