1 section and 2 cells but 4 indexPath.row - swift

Swift 4.
I want to return two cells in one section, so in my class CollectionViewController I do :
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1 }
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2 }
I see two cells but if I print indexPath.row in the code below (still in the same class), I see 0 1 0 1. Why is it not only one 0 1as I have only two cells in one section ?
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell
print(indexPath.row)
return cell
}

cellForItemAt is getting called four times. Your numberOfItemsInSection is hard-coded for 2. When the view loads cellForItemAt is called twice (once for each cell). It is then getting called twice again when you call reloadData() from your DispatchQueue.main.async closure.
Updated - How to avoid the first call:
You need to store your cell data in an array, and only populate the array just before you call reloadData(). Thus, the array will be empty when the view is first loaded.
var yourArray = [YourObject]() //Empty Array
//..
DispatchQueue.main.async {
//append your two items to the yourArray
yourArray.append(/*cell1data*/)
yourArray.append(/*cell2data*/)
self.collectionView?.reloadData()
}
//..
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return yourArray.count
}

Related

Collection view loading only one cell at a time

Edited
I am using custom collection cells to load in collectionview. But when the collection view loadeds expecting behaviour cellforindex delegate will call for 3 indexpath but in this case only calling 0th indexpath 3 time.
override func viewDidLoad()
{
super.viewDidLoad()
let nib = UINib(nibName: "cellName", bundle: nil)
self.collectionvView?.register(nib, forCellWithReuseIdentifier: "cellId")
}
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
print("indexpath.row ----------------- ",indexPath.row)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId",for: indexPath) as! DetailCollectionViewCell
return cell
}
Check All This
self.arrIds.count = 3
numberOfSections = 1
numberOfItemsInSection
cellForItemAt

Collection view inside table view

I have the following problem.
In my project I have a table view with multiple sections and one row in every section. Inside row I have a collection view.
Collection view items count depending on section in which the collection is located.But I do not understand how to access section number when I call func numberOfItemsInSection for collection view.
Here is my code:
ViewController.swift
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
TableCell.swift
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//TODO ?????? How can i get here section of table view
}
Thanks!
Create an array in UITableViewCell subclass and use that array in collectionview datasource methods
class CustomCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
var collectionData = [String]()
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionData.count
}
}
In tableView cellForRowAt method assign value to the array and reload colletion view
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as? CustomCell
cell?.collectionData = []//assign data here based on indexPath.section
cell?.collectionView.reloadData()
return cell!
}
Here you can use object oriented approach, in Your tableview cell create a variable tableSectionNumber. Like
class YourCell: UITableViewCell {
public var tableViewSectionNumber: Int = 0;
....
Now here in collectionView numberOfItemsInSection method, you can access it
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//TODO ?????? How can i get here section of table view
self.tableViewSectionNumber // its here
}
Now you can set this value in the cell in your ViewController, when you are populating the cell in TableView cellForRowItem method, Like
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.tableViewSectionNumber = indexPath.section // here you set the section number in cell
}

NSCollectionViewItems are not visible

I am trying to show items in a subclass of NSCollectionViewItem in an NSCollectionView. I can see that the NSCollectionViewDataSource gives the right number of items and is called the right number of times
extension Document: NSCollectionViewDataSource {
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return self.attachedFiles?.count ?? 0
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let attachment = self.attachedFiles![indexPath.item]
let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "AttachmentCell"), for: indexPath)
item.imageView?.image = attachment.thumbnailImage
item.textField?.stringValue = attachment.fileExtension ?? ""
return item
}
}
but the items are not shown in the GUI. I check that item.view.isHidden is false, but is there anything I need to do to make the items visible? Of course, there is also the possibility that they are never added to the collection even though the data source functions are called, but in that case my question would be how to fix that?

CollectionView sections

I have a collectionview and I want it to be of n section where each section has a ten of cells, my problem is: Maybe n equals thirty five, in this case I want to show 3 section with ten of cells and the last section with just five.
If array count is 35 return count/10 if count%10 is 0 else return count/10+1 in numberOfSections method
In numberOfItemsInSection method multiply current section with 10 and subtract from count. return min value of 10 or subtracted value
In cellForItemAt method multiply section with 10 and add row to get the array index
class ViewController: UIViewController, UICollectionViewDataSource {
var arr = Array(1...35)
func numberOfSections(in collectionView: UICollectionView) -> Int {
return (arr.count/10) + (arr.count%10 == 0 ? 0 : 1)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return min(10,arr.count - (10*section))
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? Cell
let currentStr = arr[(indexPath.section*10)+indexPath.item]
cell?.label.text = "\(currentStr)"
return cell!
}
}
You can simply implement UICollectionViewDataSource methods and configure collectionView(_:numberOfItemsInSection:) method based on the each section for number of cells.
let n = 35 //It specify the total elements count
func numberOfSections(in collectionView: UICollectionView) -> Int {
return n/10
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch section {
case (n/10):
return (n % 10)
default:
return 10
}
}
In the above code, the collectionView will have
(n % 10) cells for last section
10 cells for other sections
Kindly clarify your conditions so I can update the code accordingly.
You can split the array into chunks using this extension
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
If count is 35 -> [10,10,10,5]
If count is 30 -> [10,10,10]
If count is 29 -> [10,10,9]
Then use the two dimensional array in collectionview delegate methods
class ViewController: UIViewController, UICollectionViewDataSource {
let array = Array(1...35)
lazy var chunkedArray = array.chunked(into: 10)
func numberOfSections(in collectionView: UICollectionView) -> Int {
return chunkedArray.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return chunkedArray[section].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
print(chunkedArray[indexPath.section][indexPath.item])
return cell
}
}

Why does my UICollectionViewController not show anything?

I'm trying to make a UICollectionViewController show a grid of cells (in which I'll later add text, likely as textViews if possible). I have:
class GridViewController : UICollectionViewController{
//(NOW GONE) #IBOutlet weak var gridViewTable = UICollectionViewController()
let arr1 : [String] = []
let arr2 : [String] = []
override func viewDidLoad(){
super.viewDidLoad()
self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "gridCell")
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 4
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath as IndexPath)
cell.backgroundColor = UIColor.red
return cell
}
}
I used the interface builder to connect white where the cells will go to the gridViewTable. Nothing shows up at all, even tho it runs and compiles. How can I get the cells to show?
please use these code:
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 4
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath as IndexPath)
cell.backgroundColor = UIColor.red
return cell
}
You don't need the outlet for a UICollectionViewController, the class itself takes care of that.
Also, make sure that the view controller's class in Interface Builder is set to GridViewController in the Identity Inspector (3rd tab from the left in the right-most pane).