In iOS 12, when does the UICollectionView layout cells, use autolayout in nib
For all solutions, note that there is no need to explicitly call reloadData
in viewDidLoad
: it will happen automatically.
Solution 1
Inspired by Samantha idea: invalidateLayout
asynchronously in viewDidLoad
.
override func viewDidLoad() {
super.viewDidLoad()
//[...]
for _ in 0 ..< 1000 {
array.append(randomKeyByBitLength(Int(arc4random_uniform(8)))!)
}
DispatchQueue.main.async {
self.collectionView.collectionViewLayout.invalidateLayout()
}
}
Solution 2
(imperfect, see DHennessy13 improvement on it)
Based on Peter Lapisu answer. invalidateLayout
in viewWillLayoutSubviews
.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
As noted by DHennessy13, this current solution with viewWillLayoutSubviews
is imperfect as it will invalidateLayout when rotating the screen.
You may follow DHennessy13 improvement regarding this solution.
Solution 3
Based on a combination of Tyler Sheaffer answer, Shawn Aukstak port to Swift and Samantha idea. Subclass your CollectionView to perform invalidateLayout
on layoutSubviews
.
class AutoLayoutCollectionView: UICollectionView {
private var shouldInvalidateLayout = false
override func layoutSubviews() {
super.layoutSubviews()
if shouldInvalidateLayout {
collectionViewLayout.invalidateLayout()
shouldInvalidateLayout = false
}
}
override func reloadData() {
shouldInvalidateLayout = true
super.reloadData()
}
}
This solution is elegant as it doesn't require to change your ViewController code. I've implemented it on branch AutoLayoutCollectionView of this sample project https://github.com/Coeur/StackOverflow51375566/tree/AutoLayoutCollectionView.
Solution 4
Rewrite UICollectionViewCell default constraints. See Larry answer.
Solution 5
Implement collectionView(_:layout:sizeForItemAt:)
and return cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
. See matt answer.
In iOS 12, when UICollectionView is created using Self Sizing cells with constraints, upon reload layout has wrong height until I scroll
I think the issue is coming from you calling:
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
in your project.
If you reset this to something like:
layoutFlow.estimatedItemSize = CGSize(width: UIScreen.main.bounds.size.width, height: 100)
Then it immediately runs smoother.
Note: It is worth noting that the estimated height you set your cells to matters. If you set it to 0 then reloadData()
will scroll the collectionView to the top. Setting an accurate value seems to work best in testing
There are still a few bugs which seem to be fixed by removing the
collectionView.collectionViewLayout.invalidateLayout()
and swapping it for something like
collectionView.reloadData()
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
I don't know the specific use that you are wanting this for so I can't fully test how it should be but invalidateLayout seems like the wrong way to reload the collectionView.
Related Topics
Using Applescript with Apple Events in MACos - Script Not Working
How to Implement iOServicematchingcallback in Swift
How to Encode an Unmanaged<Seckey> to Base64 to Send to Another Server
Getting a Let Value Outside a Function
Iphonex Not Call Prefersstatusbarhidden
Swift Operator "*" Throwing Error on Two Ints
Safe to Signal Semaphore Before Deinitialization Just in Case
Swift Realm Property '*' Has Been Added to Latest Object Model Migration
Xcode 6, Swift - Read Standard Input (Console) to String
Realitykit as a Framework to Build 3D Nonar Apps
Flip Arfaceanchor from Left-Handed to Right-Handed Coordinate System
Nsimage Getting Resized When I Draw Text on It
Swift 2.0 Get Mirrored Superclass Properties
Add Skreferencenode/Skscene to Another Skscene in Spritekit
Add a Border with Cornerradius to an Image in Swiftui Xcode Beta 5