我想编写一个使用AutoLayout创建UICollectionView的程序,但遇到了一些问题。
第一次尝试:
我首先创建了一个懒加载的UICollectionView,并在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)
}
这种方法导致了以下错误:
应用程序终止,原因是未捕获的异常 '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...
}
使用这种方法后,我得到了一个空白屏幕。使用调试器发现数据源委托方法被调用(numberOfItemsInSection
和numberOfSectionsInCollectionView
),但没有其他委托方法被调用(sizeForItemAtIndexPath
和cellForItemAtIndexPath
)。
因此,我决定摆脱自动布局并查看事情的运作方式。
第三个测试:
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 !!!
}
一切都运作正常。
因此,我的问题是:是否有一种方法可以使用自动布局来编程使用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)
}