ExpandableCell icon indicating copy to clipboard operation
ExpandableCell copied to clipboard

Crash on reloadData() after changing the number of expandable rows

Open neokree opened this issue 6 years ago • 4 comments

Hello,

After changing the number of expandable rows in my dataset and call reloadData, the app crashes. This is caused by fatal error: Index out of range from this line. After some debugging I think that the problem is about the delegate method func expandableTableView(_ expandableTableView: ExpandableTableView, heightsForExpandedRowAt indexPath: IndexPath) -> [CGFloat]? which is not called for each row after the dataset change.

I'm using: XCode 9.0.1 Swift 4 ExpandableCell 1.2.0 installed with cocoapods

UPDATE The crash seems to occur only if the updated dataset have the expandable row open when reloadData() is called. If I call:

self.tableView.closeAll()
self.tableView.reloadData()
self.tableView.open(at: indexPath)

from the func expandableTableView(_ expandableTableView: ExpandableTableView, didSelectRowAt indexPath: IndexPath) method all works as it should, however is not the best solution, because the row is opening, closing and opening again (and the animation will broke).

neokree avatar Oct 31 '17 14:10 neokree

can you share your code ?

hadiidbouk avatar Nov 07 '17 08:11 hadiidbouk

I have experienced same issue @neokree described. I found that func expandableTableView(_ expandableTableView: ExpandableTableView, heightsForExpandedRowAt indexPath: IndexPath) -> [CGFloat]? method of ExpandableDelegate is not called after tableView.reloadData() call. So object of ExpandableProcessor got expired data in expandableData.expandedHeights property. And in func expandedHeight(at indexPath: IndexPath) -> CGFloat? method it throws Index out of range exception trying to access array with updated IndexPath. Actually delegate method is called only in func open(indexPath: IndexPath, delegate: ExpandableDelegate). But it should be called on reloadData() before accessing expandableData.expandedHeights property.

Also if you call

self.tableView.closeAll()
self.tableView.reloadData()

it will lead to another crash with inconsistency exception. self.deleteRows(at: expandedIndexPaths, with: animation) throws exceptions if expandedIndexPaths array is empty. So you need to check it before call deleteRows method.

nadein avatar May 14 '18 13:05 nadein

Hello, It would be helpful for you;

// TableView
@IBOutlet private var tableView: ExpandableTableView!

// Table Data
var dataArray

// Table Refresh Data
var newDataArray

Before reloading table view data with the new array,

if dataArray != newDataArray {
         tableView.closeAll()
                    
         dataArray= newDataArray
         DispatchQueue.main.async {
                 self.tableView.reloadData()
         }
}
func expandableTableView(_ expandableTableView: ExpandableTableView, numberOfRowsInSection section: Int) -> Int {
        return dataArray.count
}

func expandableTableView(_ expandableTableView: ExpandableTableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let data = dataArray[indexPath.row]
///////// Set the table view cell with the data value /////////
        return cell
}

bejaxer avatar May 24 '20 00:05 bejaxer

Hello,

Was this ever solved?

armandotorres-33 avatar Aug 26 '20 07:08 armandotorres-33