Свойства для пользовательского класса UIView не устанавливаются при вызове и добавляются в UIScrollview - PullRequest
1 голос
/ 07 февраля 2020

У меня есть простой класс UIView, который я хочу sh добавить в UIScrollView. Я смог добавить UIView в виде массива в UIScrollView без каких-либо проблем, кроме тех случаев, когда я пытаюсь установить одно из свойств представлений, например, изображение или какой-либо текст, он не отображается, когда я добавляю UIView в UIScrollView. Я надеюсь, что в этом есть смысл. Вот код:

Для класса UIView:


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. Это просто бланк с белым фоном.

Есть идеи?

1 Ответ

1 голос
/ 07 февраля 2020

Вы можете приблизиться к тому, что вы хотите, изменив функцию 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)
    }
}
...