调用和添加到 UIScrollview 时未设置自定义 UIView class 的属性

Properties for custom UIView class not being set when called and added to a UIScrollview

我有一个简单的 UIView class,我想将其添加到 UIScrollView。我已经能够将 UIView 作为数组添加到 UIScrollView 而没有任何问题,除了当我尝试设置其中一个视图属性(例如图像或某些文本)时,当我将 UIView 添加到UIS 滚动视图。我希望这是有道理的。这是代码:

对于 UIView class:


import UIKit

class ScrollViewSlide: UIView {


    lazy var mainImageForSubview : UIImageView = {
        let mI = UIImageView()
        mI.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
        return mI
    }()

    lazy var mainLabel : UILabel = {
        let mL = UILabel()
        mL.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
        mL.center.x = center.x
        mL.center.y = center.y

        return mL
    }()

    //initWithFrame to init view from code

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    private func setupView() {
        backgroundColor = .white
        contentMode = .scaleAspectFit
        addSubview(mainImageForSubview)
        addSubview(mainLabel)
    }
}

这是主要的 ViewController 代码:


import UIKit
import TinyConstraints

class ViewController: UIViewController, UIScrollViewDelegate {

    // MARK: - Properties

    lazy var contentViewSize = CGSize(width: self.view.frame.width * 3, height: self.view.frame.height * 0.6)



    // MARK: - Views


    lazy var pageIndicator : UIPageControl = {
        let pI = UIPageControl()
        pI.frame = CGRect()
        return pI
    }()

    lazy var scrollView : UIScrollView = {
        let view = UIScrollView(frame: .zero)
        view.backgroundColor = .white
        view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height * 0.6)
        view.contentSize = contentViewSize
        view.delegate = self
        return view
    }()


    // MARK: - View Controller Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        view.backgroundColor = .white
        view.addSubview(scrollView)

        let mySlides = loadSlides()

        setUpViewsForScrollView(slides: mySlides)
        scrollView.isPagingEnabled = true

        loadPageIndicator(mySlides)
    }

    func loadSlides() -> [UIView] {

        let container1 = ScrollViewSlide()
        container1.mainImageForSubview.image = UIImage(named: "cricket1")
        container1.mainLabel.text = "Container1"

        let container2 = ScrollViewSlide()
        container2.mainImageForSubview.image = UIImage(named: "cricket2")
        container2.mainLabel.text = "Container2"

        let container3 = ScrollViewSlide()
        container3.mainImageForSubview.image = UIImage(named: "crisp_ocean")
        container3.mainLabel.text = "Container3"

        return [container1, container2, container3]
    }


    func setUpViewsForScrollView(slides : [UIView]) {
        for container in slides {
            scrollView.addSubview(container)
        }
    }

    func loadPageIndicator(_ mySlides : [UIView]) {
        let myPageIndicator = pageIndicator
        myPageIndicator.numberOfPages = mySlides.count
        myPageIndicator.backgroundColor = .black
        myPageIndicator.frame = CGRect(x: self.view.frame.width * 0.5, y: 500, width: 100, height: 30)
        myPageIndicator.center.x = view.center.x
        self.view.addSubview(myPageIndicator)
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
        pageIndicator.currentPage = Int(pageIndex)
    }
}

特别是当我在 loadSlides() 中设置属性时,它们不会转移到 UIScrollView。它只是白色背景的空白。

有什么想法吗?

通过将 loadSlides() 函数更改为:

,您可以更接近您想要的结果
func loadSlides() -> [UIView] {

    // instantiate with a frame
    let container1 = ScrollViewSlide(frame: scrollView.frame)
    container1.mainImageForSubview.image = UIImage(named: "cricket1")
    container1.mainLabel.text = "Container1"

    // instantiate with a frame
    let container2 = ScrollViewSlide(frame: scrollView.frame)
    container2.mainImageForSubview.image = UIImage(named: "cricket2")
    container2.mainLabel.text = "Container2"

    // move container2 to the right of container1
    container2.frame.origin.x = container1.frame.origin.x + container1.frame.size.width

    // instantiate with a frame
    let container3 = ScrollViewSlide(frame: scrollView.frame)
    container3.mainImageForSubview.image = UIImage(named: "crisp_ocean")
    container3.mainLabel.text = "Container3"

    // move container3 to the right of container2
    container3.frame.origin.x = container2.frame.origin.x + container2.frame.size.width

    return [container1, container2, container3]
}

但是,正如我在评论中提到的,从长远来看,通过学习自动布局 运行,你会过得更好。


编辑

这是您的代码,已修改为使用自动布局而不是显式框架:

class ScrollViewSlide: UIView {

    lazy var mainImageForSubview : UIImageView = {
        let mI = UIImageView()
        return mI
    }()

    lazy var mainLabel : UILabel = {
        let mL = UILabel()
        return mL
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    private func setupView() {
        backgroundColor = .white
        contentMode = .scaleAspectFit
        addSubview(mainImageForSubview)
        addSubview(mainLabel)

        mainImageForSubview.translatesAutoresizingMaskIntoConstraints = false
        mainLabel.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([

            // constrain main image to all 4 sides
            mainImageForSubview.topAnchor.constraint(equalTo: topAnchor),
            mainImageForSubview.bottomAnchor.constraint(equalTo: bottomAnchor),
            mainImageForSubview.leadingAnchor.constraint(equalTo: leadingAnchor),
            mainImageForSubview.trailingAnchor.constraint(equalTo: trailingAnchor),

            // constrain main label centered X and Y, height = 30
            mainLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
            mainLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            mainLabel.heightAnchor.constraint(equalToConstant: 30.0),

        ])
    }
}

class SlidesViewController: UIViewController, UIScrollViewDelegate {

    // MARK: - Properties

    // using auto-layout, so no need for contentViewSize
    //lazy var contentViewSize = CGSize(width: self.view.frame.width * 3, height: self.view.frame.height * 0.6)

    // MARK: - Views

    lazy var pageIndicator : UIPageControl = {
        let pI = UIPageControl()
        pI.frame = CGRect()
        return pI
    }()

    lazy var scrollView : UIScrollView = {
        let view = UIScrollView(frame: .zero)
        view.backgroundColor = .white
        view.delegate = self
        return view
    }()

    lazy var stackView: UIStackView = {
        let v = UIStackView()
        v.axis = .horizontal
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 0
        return v
    }()

    // MARK: - View Controller Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        view.backgroundColor = .white

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

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        stackView.translatesAutoresizingMaskIntoConstraints = false

        let mySlides = loadSlides()

        setUpViewsForScrollView(slides: mySlides)

        loadPageIndicator(mySlides)

        let v = view.safeAreaLayoutGuide
        let g = scrollView.contentLayoutGuide

        NSLayoutConstraint.activate([

            // constrain scroll view to top, leading, trailing
            scrollView.topAnchor.constraint(equalTo: v.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: v.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: v.trailingAnchor),

            // constrain scroll view height to 60% of view height
            scrollView.heightAnchor.constraint(equalTo: v.heightAnchor, multiplier: 0.6),

            // constrain stack view to all 4 sides of scroll view's contentLayoutGuide
            stackView.topAnchor.constraint(equalTo: g.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor),

            // constrain stack view height equal to scroll view height
            stackView.heightAnchor.constraint(equalTo: scrollView.heightAnchor),

        ])

        scrollView.isPagingEnabled = true

    }

    func loadSlides() -> [UIView] {

        let container1 = ScrollViewSlide()
        container1.mainImageForSubview.image = UIImage(named: "cricket1")
        container1.mainLabel.text = "Container1"

        let container2 = ScrollViewSlide()
        container2.mainImageForSubview.image = UIImage(named: "cricket2")
        container2.mainLabel.text = "Container2"

        let container3 = ScrollViewSlide()
        container3.mainImageForSubview.image = UIImage(named: "crisp_ocean")
        container3.mainLabel.text = "Container3"

        return [container1, container2, container3]
    }

    func setUpViewsForScrollView(slides : [UIView]) {
        for container in slides {
            stackView.addArrangedSubview(container)
            container.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
        }
    }

    func loadPageIndicator(_ mySlides : [UIView]) {
        let myPageIndicator = pageIndicator
        myPageIndicator.numberOfPages = mySlides.count
        myPageIndicator.backgroundColor = .black

        self.view.addSubview(myPageIndicator)

        myPageIndicator.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            // width = 100, height = 30
            myPageIndicator.widthAnchor.constraint(equalToConstant: 100.0),
            myPageIndicator.heightAnchor.constraint(equalToConstant: 30.0),
            // constrain top to 12-pts below bottom of scroll view
            myPageIndicator.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 12.0),
            // constrain centerX to centerX of scroll view
            myPageIndicator.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor, constant: 0.0),
        ])
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
        pageIndicator.currentPage = Int(pageIndex)
    }
}