Reputation: 9660
This is driving me crazy! I have a UICollectionViewController
as shown below:
class PhrasesCompactCollectionViewController: UICollectionViewController
The numberOfSections
and cellForItemAt
are being called but the sizeForItemAtIndexPath
is never called. I am using the same exact code somewhere else and it fires correctly. I am using Xcode 8 Beta 6.
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 120, height:120)
}
Upvotes: 117
Views: 71963
Reputation: 295
Don't forget to use UICollectionViewDelegateFlowLayout
. Set the spacings in xib/storyboard
and resize the cell with below-updated function for newer Swift versions. Happy coding !!
@objc(collectionView:layout:sizeForItemAtIndexPath:)
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let numberOfItemsPerRow:CGFloat = 5
if let collection = self.collectionView {
let width = collection.bounds.width / numberOfItemsPerRow
return CGSize(width: width, height: 36)
} else {
return CGSize(width: 0, height: 0)
}
}
Upvotes: -1
Reputation: 942
In Swift 3+ Use this method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}
If You are using UICollectionView then make sure that your class complies both Delegate
UICollectionViewDelegate
UICollectionViewDelegateFlowLayout
Upvotes: 66
Reputation: 7129
First class need to confirm to UICollectionViewDelegateFlowLayout. Then you need to write following code in viewDidLoad():
//To tell the UICollectionView to use your UIViewController's UICollectionViewDelegateFlowLayout methods
collectionView.delegate = self
// If you want to set your own collection view flow layout
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view
self.collectionView?.setCollectionViewLayout(layout, animated: true)
By using this code UICollectionViewDelegateFlowLayout method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
will get called, you can set size in this method.
Upvotes: 13
Reputation: 14831
I managed to fix the same issue by calling
collectionView.delegate = self
BEFORE
collectionView.dataSource = self
I have static items and never reload the data.
Apparently setting the dataSource triggers the loading of the collection data synchronously, so if the delegate is not set at this point, then sizeForItemAtIndexPath
never gets called (unless reloadData
is called later).
Upvotes: -1
Reputation: 29
may you set the wrong layout: UICollectionViewLayout
, actually this layout should be UICollectionViewFlowLayout
this like
Upvotes: 0
Reputation: 1539
Just add: UICollectionViewDelegateFlowLayout
class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}
Upvotes: 0
Reputation: 10839
Swift 5
All these steps are required :
UICollectionViewDelegate, UICollectionViewDataSource
collectionView.delegate = self
and collectionView.dataSource = self
as :
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: 100, height:100)
}
Upvotes: 35
Reputation: 722
Three things you need to check if no answer works:
Implement FlowLayout Delegate : class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout
Use method for size of item for swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width)
}
Select Estimate size = None
in Inspect element of UICollectionView.
Upvotes: 8
Reputation: 1723
I had the same problem. The one thing that helped me was to make the 'Estimated Size' for the Cell Size under the collectionView size inspector 'None'.
Upvotes: 78
Reputation: 39
I had the same problem and nothing would fix it. I had a yellow warning saying to make it private because it came close to another function defined by the Layout Delegate. What fixed it for me was:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
Notice the difference from "sizeForItemAtIndexPath" to the correct "sizeForItemAt".
I tore my hair out for days trying to figure this out and it finally worked. Below I will include all of my function to show you how I also "hid" a cell by making the height equal to 0.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
if (findIndex! % 2 == 0){
// Even index, show cell
return CGSize(width: screenWidth, height: 246)
}
else {
return CGSize(width: screenWidth, height: 0)
}
}
Upvotes: 2
Reputation: 797
Make sure you put this in viewDidLoad()
collectionView.delegate = self
Upvotes: 2
Reputation: 4594
I had this issue last night. Finally solved it at midnight when I realised 'didSelectItemAtIndex' method was not closed off with a closure bracket "}"
I added a closure bracket at the very bottom of the class when asked by the compile error. So in effect all the methods below 'didSelectItemAtIndex' were inside that method.
Posting here just in case anyone else wastes 4 hours of their evenings on this one :-(
Upvotes: -2
Reputation: 307
For me (in Swift 3.1) the method must be declared public like this:
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize()
}
Don't forget to make it public.
Upvotes: -14
Reputation: 1287
Swift 3
To set Cell Size of UICollectionView, you need to create and customise object of UICollectionViewFlowLayout
. Customise the properties and set that layout object to the UICollectionView object.
Change cellheight and cell cellWidth objects according to your requirement (the cell hight and width you want).
override func viewDidLoad() {
super.viewDidLoad()
let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
let cellSize = CGSize(width: cellWidth , height:cellheight)
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //.horizontal
layout.itemSize = cellSize
layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
layout.minimumLineSpacing = 1.0
layout.minimumInteritemSpacing = 1.0
myCollectionView.setCollectionViewLayout(layout, animated: true)
myCollectionView.reloadData()
}
Make Sure: if you added sizeForItemAt indexPath method then must REMOVE the method...
Remove Below Method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
}
Upvotes: 17
Reputation: 7187
You need to specify that you implement the protocol UICollectionViewDelegateFlowLayout
in your class declaration.
class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
Upvotes: 282