jamryu
jamryu

Reputation: 698

'UICollectionView must be initialized with a non-nil layout parameter' problem arises even when layout parameter is set

You can see from the code below that layout parameter has been set inside ViewDidLoad(), but it gives me an error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'

var layer: UICollectionViewFlowLayout = {

        var item = UICollectionViewFlowLayout()

        item.itemSize = CGSize(width: 100, height: 100)

        return item

    }()

UICollectionView object has been set in property initializer because obviously I want this UICollectionView object to be accessible globally:

var dataCollectionViews = UICollectionView()

viewDidLoad(){

dataCollectionViews = UICollectionView(frame: CGRect(x: 0, y: 0, width: 0, height: 0) , collectionViewLayout: self.layer)

        view.addSubview(dataCollectionViews)

        self.dataCollectionViews.delegate = self
        self.dataCollectionViews.dataSource = self
        self.dataCollectionViews.register(UICollectionViewCell.self, forCellWithReuseIdentifier: collectionViewReuse)
        self.dataCollectionViews.layer.cornerRadius = 10
        self.dataCollectionViews.translatesAutoresizingMaskIntoConstraints = false
        self.dataCollectionViews.isHidden = true

  changed()
}

When I moved contents inside changed() to inside of viewDidLoad() and initialized dataCollectionViews inside of viewDidLoad(), everything worked as intended, showing UICollectionView object when selecting first button of segmented Control.

@objc func changed() {

    if segmentTime.selectedSegmentIndex == 0 {

        self.dataCollectionViews.isHidden = false

        let dataCollectionTop = NSLayoutConstraint(item: self.dataCollectionViews, attribute: .top, relatedBy: .equal, toItem: sortLabel, attribute: .bottom, multiplier: 1.0, constant: 10)

        let dataCollectionLeft = NSLayoutConstraint(item: self.dataCollectionViews, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 10)

        let dataCollectionRight = NSLayoutConstraint(item: self.dataCollectionViews, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: -10)

        let dataCollectionHeight = NSLayoutConstraint(item: self.dataCollectionViews, attribute: .height, relatedBy: .equal, toItem: self.view, attribute: .height, multiplier: 520/812, constant: 0)

        let dataCollectionWidth = NSLayoutConstraint(item: self.dataCollectionViews, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 355/375, constant: 0)

        NSLayoutConstraint.activate([dataCollectionLeft, dataCollectionRight, dataCollectionHeight, dataCollectionWidth, dataCollectionTop])

    }

    if segmentTime.selectedSegmentIndex == 1 {



    }

    if segmentTime.selectedSegmentIndex == 2 {



    }

}

I'd love to try to set dataCollectionViews object in property initializer but I know it is not possible, but it seems like dataCollectionViews needs be initialized with UICollectionViewFlowLayout() on first try. What other alternative is available?

Upvotes: 0

Views: 184

Answers (1)

Kaan Dedeoglu
Kaan Dedeoglu

Reputation: 14841

How about something like this?

private lazy var collectionView: UICollectionView = {
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: 188.0, height: 268.0)

    let result: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
    result.register(CellClass.self, forCellWithReuseIdentifier: "cell")
    result.dataSource = self
    result.delegate = self
    return result
}()

Upvotes: 1

Related Questions