I have added a UICollectionVIew to a vertical Stack View. I connected both datasource and Delegate from storyboard and added the delegate/datasource from the code as well.
However, the following method is not being called at all:
internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { ... }
But, the methods
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
are being called.
So, I moved the UICollectionVIew out of the vertical Stack View and it was working then. But, the method is not being called when the UICollectionVIew is in the vertical Stack View.
How can I solve this?
Same happen with me in past with TableView but not with UIStackView
If numberOfSections and numberOfItemsInSection called and cellForItemAt not called then only possible reason your CollectionView height is 0
Because of that your cell didn't get enough space to show cell
You can Check same thing by adding height of your collection view to 0
in to the case where you said I moved the UICollectionVIew out of the vertical Stack View and it was working then.
Related
I have a UICollectionView with the following settings:
Estimate Size = None
Content Insets = Never
Scroll Direction = Vertical
Paging Enabled = true
When I scroll to the second cell, the cellForItemAt method is triggered twice, with indexes 1 and 2 at the same time, and accordingly, when I swipe to the last cell, the cellForItemAt method does not work.
cellForItemAt does not work correctly only on swiping to the second cell, in all other cases it is OK (one index per swipe)
I also noticed that cellForItemAt is triggered not as soon as a new visible cell appears, but with a delay (about 100 pixels on top, the standard height is 568 pixels of cells)
Because of this problem, I do not work cellForItemAt on the last cell, also in the cells there are photos that are loaded by URL (I tried without loading images, the problem is the same), and they are in random cells, this is also a problem.
I do not know how to explain and solve this issue, thank you for any help
UP
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib(nibName: TestCell.identifier, bundle: nil), forCellWithReuseIdentifier: TestCell.identifier)
collectionView.dataSource = self
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("cellForItemAt: \(indexPath.item)")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TestCell.identifier, for: indexPath) as! TestCell
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
If I scroll to the second cell, the cellForItemAt works twice, and when the last cell, the cellForItemAt does not work at all. Accordingly, the configuration methods for the last cell do not work. I gave a simple example, but the problem is the same.
How do I load a cell on a user's scroll correctly?
As #PaulW11 said in his comment, your data source's collectionView(_:cellForItemAt:) method can be called at any time, with any indexPath. You should code your data source to provide any cell, for any valid indexPath, at any time, in any order.
The only limitation is that the collection view first calls your data source's numberOfSections(in:) and collectionView(_:numberOfItemsInSection:) methods, and won't ask for a cell for an indexPath that is out of the valid ranges indicated by those methods. Other than that, you should not make any assumptions about the cells the collection view will ask for, or the order in which it requests them.
This maybe a duplicate post. But I haven't found any solution in the answers given in previous questions.
Basic checks from my side that I have done.
No errors on the constraint that I have put on CollectionView and CollectionViewCell.
When numberofitemsinsection is called, it always returns more than 0.
Reusable identifier is tagged for both CollectionView and CollectionViewCell
All links for ui objects are at place.
CollectionViewCell size is set as default.
Some more information on my code.
class StickerGridCollectionViewController: UICollectionViewController{
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return stickerPackList.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
/*some code*/
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
/*some code*/
}
}
I checked all the answers here, but didn't find my answer yet.
Any clue why I might be getting this issue?
Update
When I open debug view hierarchy, I find out that collectionview is taking correct area, but views which were supposed to be inside collectionview are flowing outside and acting abnormally.
Moreover I see UICollectionView inside UiCollectionView.
Any reason, why this abnormal behaviour might occur?
I am trying to create a menu where top horizontal scrolling view contains the menu categories. When I tap on one of the menu categories, ads related to the category appears.
When First is selected
--**First**---|--Second--|---Third--|--Fourth--| (scrolling categories)
------------------------------------------------------------------
\\\FirstA\\\ \\\FirstB\\\ \\\FirstC\\\ \\\FirstD\\\
\\\FirstA\\\ \\\FirstB\\\ \\\FirstC\\\ \\\FirstD\\\
------------------------------------------------------------------
When Second is selected
--First---|--**Second**--|---Third--|--Fourth--| (scrolling categories)
------------------------------------------------------------------
\\\SecondA\\\ \\\SecondB\\\ \\\SecondC\\\ \\\SecondD\\\
\\\SecondA\\\ \\\SecondB\\\ \\\SecondC\\\ \\\SecondD\\\
------------------------------------------------------------------
When I tap on First Category, data related to first comes as a collectionView. Similarly, when I tap on second Category, data related to second comes in the UICollectionView.
Now I am thinking of doing it in a UITableViewCell with two UICollectionViews. First UICollectionView will contain categories and second UICollectionView will contain data related to categories.
But I have never used two UICollectionViews in a single UITableViewCell.
So I am asking is it the correct approach for this type of requirement or should I do it in some other manner.
You could subclass an UITableViewCell, add UICollectionView as subview, conform UICollectionViewDataSource and UICollectionViewDelegate
here's sample code using xib
class CollectionViewTVC: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
}
extension CollectionViewTVC: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return items
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
// return size
}
}
extension CollectionViewTVC: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// select cell action
}
}
Why don’t you use two table view cells, one for every collectionViewu?
I am trying to create simple educational app about movies, and I need to create movie frames horizontal scroller.
I create collection view for that:
But if I build it for another target (iPhone 6s Plus for example), I have this:
How to solve this problem?
My scene controller code (Swift 3):
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
cell.backgroundColor = UIColor.black
// Configure the cell
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I think that you can try to implement the method of UICollectionView delegate:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(yourHeight, self.view.frame.size.width)
}
in this way, your collectionView-cell inside in tableView will appear as big as the screen.
First I want to say something about UITableViewAutomaticDimension you use, in case you not exactly understand how it works.
Your expectations probably are, that UITableViewAutomaticDimension will infer tableView to make a cell with size of entire tableView, but it doesn't work this way.
UITableViewAutomaticDimension is just infers tableView, that inner size of your cell will be used as a returned here; so if you add some constraints, views with constraints, or whatever inside your tV, its size will be used.
and second - your comment doesn't make sense at all for me, because your posted code isn't related to cell of collectionView and I can't comment anything related to size of its cells
EDITED:
to make all cells with width of your screen, return correct size from delegate method of collectionViewFlowLayout - sizeForItem
I have added a UICollectionView in my app. I have given its constraints like leading, trailing, top & some fixed height of the collection view. It is showing all items. But I am not able to scroll it. Please tell what is the issue?
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("count is \(arr_collection.count)")
return arr_collection.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let identifier="col_cell"
let cell:CollectionCell
cell=collectionView.dequeueReusableCellWithReuseIdentifier(identifier, forIndexPath: indexPath ) as! CollectionCell
cell.img_cell.image=UIImage(named: arr_collection[indexPath.row])
print("arr collection is \(arr_collection[indexPath.row])")
return cell
}
CollectionViews in Interface builder by default have "Bounces" property enabled, but you must specify what direction it bounces in. If you don't, and the content of the Collection View does not exceed the boundaries of the collection view, you won't be able to scroll.