** Note that this issue does NOT happen on ios 9 but on ios 10 only.
I have a collection view with cell called "MyCell". Each MyCell contains a MyView, and MyView contains a MyLabel. 2 seconds after the viewcontroller did load, I trigger a call "setNeedsLayout" to one of visibleCells of collectionView to refresh its MyLabel's content.
If my MyLabel's adjustsFontSizeToFitWidth is not set, it works ok. But if I assign adjustsFontSizeToFitWidth = true, app will hang up with an infinite number of calls to "layoutSubviews".
The sample code is as following (~120 lines). If I comment out line #18, it works ok but the font is not scaled as I expected. If I leave it as is, app will hang up and crash due to out-of-memory error.
Thanks for your help.
import UIKit
import SnapKit
class MyView: UIView {
var myText: String = "" {
didSet {
self.setNeedsLayout()
}
}
let myLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.whiteColor()
myLabel.adjustsFontSizeToFitWidth = true
self.addSubview(myLabel)
myLabel.snp_remakeConstraints { (make) in
make.size.equalTo(CGSizeMake(200, 50))
make.center.equalTo(self)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.myLabel.text = self.myText
}
}
class MyCell: UICollectionViewCell {
let myView = MyView()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.darkGrayColor()
self.addSubview(myView)
myView.snp_remakeConstraints { (make) in
make.center.equalTo(self)
make.size.equalTo(CGSizeMake(210, 60))
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.myView.myText = "Hello!!!"
}
}
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
lazy var myCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Vertical
layout.minimumInteritemSpacing = 1.0
layout.minimumLineSpacing = 1.0
let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.registerClass(MyCell.self, forCellWithReuseIdentifier: "MyCell")
return collectionView
}()
let myButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(myCollectionView)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2 * NSEC_PER_MSEC)), dispatch_get_main_queue(), {
self.myCollectionView.visibleCells().last?.setNeedsLayout()
})
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath)
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(self.view.bounds.width, self.view.bounds.height)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
}