首页 > 解决方案 > ViewController 包含子类化

问题描述

为了提高我的“远离大型视图控制器”,我正在尝试一些包含视图控制器的东西。

这就是我想要的:

我期待这样的事情:

在此处输入图像描述

这是我试图实现这一目标的代码:

import UIKit

/**
Base class
*/
class PrototypeStackViewController: UIViewController {

    private let scrollView: UIScrollView = {
        let s = UIScrollView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.contentMode = .scaleToFill
        return s
    }()

    private let stackView: UIStackView = {
        let s = UIStackView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.axis = .vertical
        s.alignment = .fill
        s.distribution = .fill
        s.contentMode = .scaleToFill
        return s
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemGray

        view.addSubview(scrollView)
        scrollView.addSubview(stackView)

        let  nstraint = stackView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor)
        stackViewHeightConstraint.priority = .defaultLow

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

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

            stackViewHeightConstraint
        ])
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func add(child: UIViewController) {
        addChild(child)
        stackView.addArrangedSubview(child.view)
        child.didMove(toParent: self)
    }

    func remove(child: UIViewController) {
        guard child.parent != nil else { return }

        child.willMove(toParent: nil)
        stackView.removeArrangedSubview(child.view)
        child.view.removeFromSuperview()
        child.removeFromParent()
    }
}

/**
Implementation of my scene
*/
class PrototypeContainmentViewController: PrototypeStackViewController {

    lazy var topViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemRed
        t.label.text = "Top View Controller"
        return t
    }()

    lazy var centerViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemGreen
        t.label.text = "Center View Controller"
        return t
    }()

    lazy var bottomViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemBlue
        t.label.text = "Bottom View Controller"
        return t
    }()

    override func loadView() {
        super.loadView()

        add(child: topViewController)
        add(child: centerViewController)
        add(child: bottomViewController)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}

/**
Sample View Controller
*/
class PrototypeSubViewController: UIViewController {

    lazy var label: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemRed

        view.addSubview(label)

        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
            label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ])
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

这是我得到的:

在此处输入图像描述

如果你仔细看,你甚至可以看到“底部视图控制器”标签——但在绿色中心视图控制器的顶部。

在我与自动布局的爱恨交织关系中,我在这里遗漏了一些东西,这是肯定的......

标签: iosswiftautolayout

解决方案


您缺少确保堆栈视图填充滚动视图宽度的宽度约束:

stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)

另外我会以这种方式设置您的标签约束:

NSLayoutConstraint.activate([
    label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
    label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
    label.top.constraint(equalTo: view.topAnchor),
    label.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])

推荐阅读