Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a UICollectionView programmatically with AutoLayout

I'm trying to create a UICollectionView programmatically with AutoLayout and I have some issues.

First Test:

In my first try I created a UICollectionView as a Lazy var and added it in the viewDidLoad like this:

lazy var collection: UICollectionView = {
        let cv = UICollectionView()
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.setCollectionViewLayout(self.flowLayout, animated: true)
        cv.dataSource = self
        cv.delegate = self
        cv.registerClass(MyViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
}()


override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(self.collection)
}

This approuch took me to this error:

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

Second Test:

So I had to use the frame/collectionViewLayout initializer and my second try looked like this:

lazy var collection: UICollectionView = {
        let cv = UICollectionView(frame: UIScreen.mainScreen().bounds, collectionViewLayout: self.flowLayout)
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.setCollectionViewLayout(self.flowLayout, animated: true)
        cv.dataSource = self
        cv.delegate = self
        cv.registerClass(MenuViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
}()


override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(self.collection)

        //Constraints was there...

}

With this approuch I got a blank screen, using debugger I found out that the datasource delegate methods was called (numberOfItemsInSection and numberOfSectionsInCollectionView), but no other delegate methods was called (sizeForItemAtIndexPath and cellForItemAtIndexPath)

So I decided to get rid of autoLayout and see the way things work.

Third Test:

 lazy var collection: UICollectionView = {
        let cv = UICollectionView(frame: UIScreen.mainScreen().bounds, collectionViewLayout: self.flowLayout)
      //  cv.translatesAutoresizingMaskIntoConstraints = false
        cv.setCollectionViewLayout(self.flowLayout, animated: true)
        cv.dataSource = self
        cv.delegate = self
        cv.registerClass(MenuViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
    }()


override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(self.collection)

        //No more constraints here !!!

}

And everything worked fine.

So, my question is: Is there a way to use UICollectionView Programmatically with AutoLayout ?

SOLUTION

After a while, I found out that my problem was in the constraints. Then I came out with this solution:

 let slice = (UIScreen.mainScreen().bounds.height / CGFloat(3.0)) 

    lazy var flowLayout:UICollectionViewFlowLayout = {
        let f = UICollectionViewFlowLayout()
        f.scrollDirection = UICollectionViewScrollDirection.Horizontal
        return f
    }()


    lazy var collection: UICollectionView = {
        let cv = UICollectionView(frame: CGRectZero, collectionViewLayout: self.flowLayout)
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.setCollectionViewLayout(self.flowLayout, animated: true)
        cv.dataSource = self
        cv.delegate = self
        cv.registerClass(MenuViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
    }()


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.collection)

        let views = ["collection":self.collection]

        var constraints =  NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[collection]-0-|", options: NSLayoutFormatOptions.AlignAllTop, metrics: nil, views: views)
        self.view.addConstraints(constraints)

        constraints =  NSLayoutConstraint.constraintsWithVisualFormat("V:|-\(slice)-[collection]-\(slice)-|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: views)
        self.view.addConstraints(constraints)
    }
like image 938
Sebastian Avatar asked Nov 18 '15 02:11

Sebastian


People also ask

How do I make UICollectionView programmatically?

To create a UICollectionView programmatically, I will create a new instance of UICollectionView by giving it a UICollectionViewFlowLayout as a parameter. The above collection view will not display any items however.

How does swift implement UICollectionView?

Select the Main storyboard from the file browser. Add a CollectionView by pressing command shift L to open the storyboard widget window. Drag the collectionView onto the main view controller. Add constraints to the UICollectionView widget to ensure that the widget fills the screen on all devices.

What is UICollectionViewFlowLayout?

A layout object that organizes items into a grid with optional header and footer views for each section.


1 Answers

After a while, I figure out that my problem was in the constraints. Then I came out with this solution:

 let slice = (UIScreen.mainScreen().bounds.height / CGFloat(3.0)) 

    lazy var flowLayout:UICollectionViewFlowLayout = {
        let f = UICollectionViewFlowLayout()
        f.scrollDirection = UICollectionViewScrollDirection.Horizontal
        return f
    }()


    lazy var collection: UICollectionView = {
        let cv = UICollectionView(frame: CGRectZero, collectionViewLayout: self.flowLayout)
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.setCollectionViewLayout(self.flowLayout, animated: true)
        cv.dataSource = self
        cv.delegate = self
        cv.registerClass(MenuViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
    }()


    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.collection)

        let views = ["collection":self.collection]

        var constraints =  NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[collection]-0-|", options: NSLayoutFormatOptions.AlignAllTop, metrics: nil, views: views)
        self.view.addConstraints(constraints)

        let stringConstraint = "V:|-\(slice)-[collection]-\(slice)-|"

        print("stringConstraint: \(stringConstraint)")

        constraints =  NSLayoutConstraint.constraintsWithVisualFormat(stringConstraint, options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: views)
        self.view.addConstraints(constraints)
    }
like image 132
Sebastian Avatar answered Sep 29 '22 23:09

Sebastian