Table view - Index out of range in cellForRowAt - ios

I call tableView.reloadData() inside of didSet{} of the items variable.
I got a crash in the cellForRowAt function only once, never before, never after with no code changes.
override func tableView(_ tableView: UITableView, number ofRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.tag = indexPath.row
let item = items[indexPath.row] //Thread 1: Fatal error: Index out of range
cell.textLabel?.text = item.title

The possible solution will be you need to handle to solve the crash.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row > items.count-1){
return UITableViewCell()
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.tag = indexPath.row
let item = items[indexPath.row] //Thread 1: Fatal error: Index out of range
cell.textLabel?.text = item.title
return cell
}
}
Maybe this will help.

I can see it happening if the table is scrolling quickly and you update the data source: it could hit a race condition where it tries to call cellForRowAt one more time before it realizes you changed the data source. As a precaution, I'd suggest always adding a check that your index is less than the array's count. Maybe it's paranoid, but better than a crash.
e.g:
Array has 100 items.
Swipe hard sending you towards bottom of table.
While scrolling, the array is updated to only have 10 items.
Table scroll asks for cell at row 99 because it didn't get the message yet.
Crash when you ask for item 99 in an array with only 10 items.

This crash appears when your index is more than array's count.
This crash may appear when scrolling the table view and table view get's updated. You are trying to fetch the index more than array count.
You can check the condition of indexpath.row less than array count.

Try using some thing like this
var fileNameArray = [Audio](){
didSet{
if fileNameArray.count > 0{
recordingListTableView.reloadData()
}
}
}
Is It required to do this ?
crash Is index out of range
Are you Re-Updating Array After this didSet Statement ? if Yes, Do not use this DidSet case here , use if Array is not going to be updated again ,
If you still want to use , Also make use of WillSet Case After didSet()

override func tableView(_ tableView: UITableView, number ofRowsInSection section: Int) -> Int {
guard let items.count > 0 else {return 0}
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.tag = indexPath.row
let item = items[indexPath.row]
cell.textLabel?.text = item.title
}
I think items array does not have any value so it does crash. So, try this above code.

Related

How to implement two xib cells and single . Array count is nil show empty one otherwise show with data cell

How to implement two xib cells and only one array, if array count is nil show empty xib cell and if array count is not nil show xib cell with data swift. Please solve the problem i have searched lot of no answer is related to me.
This example assumes your data array is named myData:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return either 1, or the count of your data, whichever is greater
return max(1, myData.count)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// if it's the first row, and your data is empty
if indexPath.row == 0 && myData.count == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "emptyCell", for: indexPath) as! EmptyCell
return cell;
}
let cell = tableView.dequeueReusableCell(withIdentifier: "dataCell", for: indexPath) as! DataCell
// populate the cell
return cell
}

How to access specific row by index

I've a table view controller in which I want to dynamically create a row (cell). How can I access row by index number in Swift? The following is what I did and now I'm stuck here.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamStats", for: indexPath) as! TeamStatsTableViewCell
return cell
}
This is my TableViewController code in which I want to check if the row is at a specific index number.
This method is a delegate method which will be called every time a cell is displayed on your UITableView. So if you want to do something with a cell in a particular index, you do the following. Please go through Apple docs and get a better understanding of what delegate methods are.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamStats", for: indexPath) as! TeamStatsTableViewCell
if indexPath.row == requiredIndex {
//Do something.
}
if indexPath.row == lastIndex { // you have the last index with you. replace this variable with that.
cell.firstlabel.text = ""
}
return cell
}
Please try this code:
if indexPath.row == 1{
//Your code
}
You can check the section :
if indexPath.section == 1{
}
It may helps to you.Thank you

Programmatically Create Static TableView / Cells

I have a UITableView, which as an example contains dynamic cells I create based on the content of an array.
I can populate these using the count of the array and indexPath to render a cell per item. I am happy with this and it works well.
I would like to try now and create static cells programmatically.
Immediately however I am stumped, how do I create this? I'm currently overriding numberOfRowsInSection and cellForRowAt indexPath as follows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[indexPath.row]
return cell
}
I suspect my first mistake is dequeueReusableCell and would really appreciate any help.
If I understood your question, you want to add a static cell in a tableView that contains dynamic cells.
If that is the case, you could hardcode this, increasing the return value here:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count+1
}
In this case, you want to add just one static cell.
In cellForRowAtIndexPath, you should define where you want to add this static cell. In the example below, it would be the first cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//should change StaticCell to the static cell class you want to use.
let cell = tableView.dequeueReusableCell(withIdentifier: "staticCell", for: indexPath) as! StaticCell
//hardcore attributes here, like cell.rowContent.text = "A text"
return cell
}
let row = indexPath.row-1
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[row]
return cell
}
It's basically about shifting the items[row] according to the number of static cells you want to use.
I'm not sure if that will work, but would be my first guess (according to my experience about that). Try this and tell me if it worked :)

App crashing when scrolling UITableView

I am creating table cells in a table view they load correctly and you can scroll down them fine but if you scroll back up the app crashes with the error fatal error: Index out of range
This is the code producing the table cells
Im quite new to coding in swift so please be clear on your answers
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return(tableRows.count)
}
var howmanyindex = 0
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ReviewControllerTableViewCell
cell.label1.text = profilerComments[tableRows[howmanyindex]]
cell.label2.text = String(profilerRatings[tableRows[howmanyindex]])
howmanyindex += 1
return(cell)
}
The problem seems to be with howmanyindex. Since you are using reusable cells, cellForRowAt is going to get called several times for a cell at a certain position if a cell goes out of the visible part of the screen.
Just use indexPath.row to index your data source array.
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ReviewControllerTableViewCell
cell.label1.text = profilerComments[tableRows[indexPath.row]]
cell.label2.text = String(profilerRatings[tableRows[indexPath.row]])
return cell
}
When tableView scrolls your howmanyindex += 1is increasing for every visible cells hence index going beyond your tableRows array, its better you use indexpath.row of tableRows.
No need to keep tracking the index of the table manually howmanyindex because it may be different from your data(or returning count) so when you fetch the data from your array it may come nil from the array and you got crashed.
So you can get the current cell index from indexPath.row
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ReviewControllerTableViewCell
cell.label1.text = profilerComments[tableRows[indexPath.row]]
cell.label2.text = String(profilerRatings[tableRows[indexPath.row]])
return(cell)
}
Use
cell.label1.text = profilerComments[tableRows[indexpath.row]]
in place of
cell.label1.text = profilerComments[tableRows[howmanyindex]]

for loop only shows first item in array when trying to display in tableView

I'm trying to display tableview cells based on items in an array but for some strange reason it will only display the first item in the array. When I use a print statement it shows the array it being iterated through correctly.
Here is the array:
var restaurants = ["Truckyard", "EasySlider", "Revolver", "Armoury"]
Here is the cellForRowAtIndexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = restaurantTableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! restaurantCell
for rest in restaurants {
cell.restaurantImageView.image = UIImage(named: rest)
cell.restaurantNameLabel.text = rest
}
return cell
}
cellForIndexPath is called once for each row. Try this instead:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = restaurantTableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! restaurantCell
cell.restaurantImageView.image = UIImage(named: restaurants[indexPath.row])
cell.restaurantNameLabel.text = restaurants[indexPath.row]
return cell
}
No need for a loop. cellForRowAt is providing you with an indexPath. Check the indexPath.row property. If you only have one section, the row is the index of the item in your array you want to access. You are basically iterating over your array for each row and this will inevitably set your last item as the title/image

Resources