使用 AutoLayout 以编程方式创建 UICollectionView

Seb*_*ian 5 ios autolayout uicollectionview swift

我正在尝试使用 AutoLayout 以编程方式创建 UICollectionView,但我遇到了一些问题。

第一次测试:

在我的第一次尝试中,我创建了一个 UICollectionView 作为 Lazy var 并将其添加到 viewDidLoad 中,如下所示:

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)
}
Run Code Online (Sandbox Code Playgroud)

这个方法把我带到了这个错误:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“UICollectionView 必须使用非零布局参数进行初始化”

第二次测试:

所以我不得不使用 frame/collectionViewLayout 初始值设定项,我的第二次尝试看起来像这样:

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...

}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我得到了一个空白屏幕,使用调试器我发现数据源委托方法被调用(numberOfItemsInSectionnumberOfSectionsInCollectionView),但没有其他委托方法被调用(sizeForItemAtIndexPathcellForItemAtIndexPath

所以我决定摆脱 autoLayout 并看看事情的工作方式。

第三次测试:

 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 !!!

}
Run Code Online (Sandbox Code Playgroud)

一切正常。

所以,我的问题是:有没有办法通过 AutoLayout 以编程方式使用 UICollectionView ?

解决方案

过了一会儿,我发现我的问题出在约束上。然后我提出了这个解决方案:

 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)
    }
Run Code Online (Sandbox Code Playgroud)

Seb*_*ian 6

过了一会儿,我发现我的问题出在约束上。然后我提出了这个解决方案:

 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)
    }
Run Code Online (Sandbox Code Playgroud)