The indexPath of a specific UITableViewCell is always nil - uitableview

After the update to Xcode8 the following code doesn't work anymore
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let cell = collectionView.superview!.superview as! UITableViewCell
let table = cell.superview!.superview as! UITableView
let indexPath = table.indexPath(for: cell)
Now the value of indexPath is always nil.
Any ideas?

I've solved the problem by replacing the last line with
let indexPath = table.indexPathForRow(at: cell.center)

Related

Swift CollectionView (fatal error: Index out of range)

I am implementing a UICollectionView inside each cell of a UITableView
Now I am getting data from an API and keeping this data in an Array, and the problem is that the UICollectionView delegate method numberOfItemsInSection is of course being called before even the array is getting filled with data so I am getting Index out of range error.
The question is how to give maybe a default value to the count being returned or how to mutate the array.
Here is the code i am using:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// let cell = collectionView.superview as! MainTableViewCell
// let index = tableView.indexPath(for: cell)
let countIndex = self.consultations[collectionView.tag].images.count
return countIndex
}
You need to check array found and it's count.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let consultationsTmp = self.consultations, let colTag = consultationsTmp[collectionView.tag],let imagesTmp = colTag.images
{
return imagesTmp.count
}
return 0
}
I solved the issue with a different method.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let cell = collectionView.superview?.superview?.superview as! MainTableViewCell
print("SSSSSSSSSSSSSSSSS\(cell)")
let index = self.tableView.indexPathForRow(at: cell.center)
print("EEEEEEEEEEEEEE\(index?.row)")
let countIndex = self.consultations[index?.row ?? 00].images.count
return countIndex
}

uicollection view within a tableview cell getting ERROR: Index out of range, why?

I have an array (4 items) of type Venue each contains an array (2 items) of imgURLs String and I am getting an ERROR: Index out of range at the following line of my collectionView cellForItemAt. I am trying to display the images for each Venue in a collectionView within the tableview cell.
let urlString = filteredVenueArray[collectionView.tag].imgURLs[collectionView.tag]
cellForItemAt function:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VenueListingCellImage", for: indexPath) as! VenueListingCellImage
let urlString = filteredVenueArray[collectionView.tag].imgURLs[collectionView.tag]
let imgURL = URL(string: urlString)
cell.configureCell(url: imgURL!)
return cell
}
EDIT: numberOfItemsInSection function
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return filteredVenueArray[collectionView.tag].imgURLs.count
}
Change this line
let urlString = filteredVenueArray[collectionView.tag].imgURLs[collectionView.tag]
To
let urlString = filteredVenueArray[collectionView.tag].imgURLs[indexPath.item]
In your code replace:
let urlString = filteredVenueArray[collectionView.tag].imgURLs[collectionView.tag]
with:
let urlString = filteredVenueArray[collectionView.tag].imgURLs[indexPath.item]
CollectionView cellForItemAt indexPath iterates your array through indexPath, so to access each item you should use indexPath.item
Here is the problem, you should use,
let urlString = filteredVenueArray[collectionView.tag].imgURLs[indexPath.item]

Deque custom cells from specific indexpath SWIFT

I have UICollectionView, I am downloading images and displaying them in the cells. My first cell is of screen width and contains a button, rest are the general cells. The application only deques the first 2 cells, There are supposed to be 3 cells.
My cellForItemAtIndexPath function:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
print("yay")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UploadNewCell", for: indexPath) as! UploadNewCell
return cell
}else if indexPath.row > 0 {
let userImages = userposts[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.fillCells(uid: uid!, userPost: userImages)
return cell
}else{
return ProfileCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("hellowold")
} else {
let selecteditem : String!
selecteditem = userposts[indexPath.row]
performSegue(withIdentifier: "lol", sender: selecteditem)
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userposts.count
}
my view:
There are supposed to be 3 images down there in the cells, One of them is dequed in the first index.
I am out of Ideas, Any ideas on the solution?
let userImages = userposts[indexPath.row]
At this point in your code, indexPath.row is > 0.
Arrays are 0-based, so the first cell (indexPath.row == 1) is getting the second item in your array (user posts[1]), which is the second image you wanted.
I can think of a couple of simple changes:
Change the index you're accessing, such as:
let userImages = userposts[indexPath.row - 1]
Add 1 to your userposts.count value in numberOfItemsInSection:
Split your collectionView into having multiple sections, so the top cell (UploadNewCell) is section 0, and the bottom three ProfileCells are a second section: this allows you to check the indexPath.section, and assign directly from row:
let userImages = userposts[indexPath.row]
Note: I would actually advise further modifying the code for the second option to create an enum for SectionType. That allows you to perform a switch over the potential values, allowing you to avoid that nasty default implementation, and boosts the readability of your code.

collection view has first cell always empty

I have a custom Collection view in a Viewcontroller , whenever my Collection View is loaded always I get my first cell empty. How to remove this empty cell.
//CollectionView functions
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return collectionData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! collectionCell
let collectionData = self.collectionData[indexPath.row]
cell.NameLbl.text = collectionData["name"] as? String
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let Info: NSDictionary = self.collectionData[indexPath.item] as! NSDictionary
let vc = self.storyboard?.instantiateViewController(withIdentifier: "edit") as! editVC
self.navigationController?.pushViewController(vc, animated: false)
}
Depends on what is the case that you should handle hiding the first element, there are tow options that you might want to implement:
1- If it is okay to remove the first object from the data source (collectionData array), then you can simply remove the first element from it:
In your view controller (viewDidLoad()) you could implement:
override func viewDidLoad() {
.
.
.
collectionData.remove(at: 0)
.
.
.
}
2- if you are required to keep the collectionData as is without removing the first element, but it should not be displayed in the UI, you will need to implement the UICollectionViewDataSource as follows:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// subtract 1
return collectionData.count - 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! collectionCell
// add 1 to indexPath.row
let collectionData = self.collectionData[indexPath.row + 1]
cell.NameLbl.text = collectionData["name"] as? String
return cell
}
That should lead to displaying the collection view as expected without editing the collectionData data source array.

Can't get the cell reference in collection view when selecting

I have a problem with a simple collection view: in the delegate didSelectItemAtIndexPath I can't get the right reference to the cell. This is my code:
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return categories.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
cell.titleLabel.text = categories[indexPath.row]["name"] as? String
cell.backgroundColor = ConversionUtilities.getUIColorFrom(categories[indexPath.row]["color"] as! String)
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
print("Cell with title: \(cell.titleLabel.text) and background color: \(cell.backgroundColor)")
collectionView.reloadData()
}
I get always when I select a cell:
Cell with title: Optional("Label") and background color: nil
and I don't know why, it's like the cellForItemAtIndexPath is not working but the same print in cellForItemAtIndexPath give me:
Cell with title: Optional("fruits") and background color:
Optional(UIDeviceRGBColorSpace 1 1 0 1)
...and yes, the cell identifier is right is "cell" and I also set up correctly in storyboard. In addition UICollectionViewDataSource and UICollectionViewDelegate are also correctly linked in IB.
Any help?
When you call dequeueReusableCellWithReuseIdentifier method, i.e.
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CategorySelectionCVCell
you get an empty cell ready to be reused, not the cell that is currently in your collection view.
Although you can get the cell from the collection view by calling
let cell = collectionView!.cellForItemAtIndexPath(indexPath) as! CategorySelectionCVCell
if all you need is the text from its label it's better to go straight to the model, i.e.
let labelText = categories[indexPath.row]["name"] as? String

Resources