今天用swift3.0写collectionView的时候遇到一个BUG
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
let string = datas[indexPath.item]
cell.label.text = string
return cell
}
-然后在MyCell 里去算Cell里label的实际宽度
override func layoutSubviews() {
super.layoutSubviews()
let string = label.text
// sizeWithFont:自己封装的方法
let size = string!.sizeWithFont(UIFont.systemFont(ofSize: 12), size: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)))
label.frame = CGRect(x: 10, y: 0, width: size.width, height: 40)
}
- 效果如下,label宽度明显不对
疑惑
- 我在cellForItemAt里面已经对cell中的label进行了赋值,在cell中取值在算宽度应该是没有问题的,
解决
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
let string = datas[indexPath.item]
cell.label.text = string
// 添加下面这一句
cell.setNeedsLayout()
return cell
}
界面就正确了
-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
一个view的fram或bounds发生变化时,系统会设置一个flag给这个view,当下一个渲染时机到来时系统会重新按新的布局来渲染视图。setNeedLayout就是我们主动为这个视图设置一个flag,告诉系统这个视图再下一个时机到来时要重新渲染,而layoutIfNeed则是告诉系统,如果设置了flag那么不用等待时机到来了,直接渲染吧。而layoutSubviews这个方法是系统调用的,我们不需要主动调用,我们只需要调用layoutIfNeed就可以了,让系统判断是否在当前时机下立即渲染