I have the following code which causes the app to crash with the error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'
I have tried multiple solutions as listed on StackOverflow but none can stop this error.
Tried:
Code:
import UIKit
import MapKit
class TableViewController: UITableViewController, UISearchResultsUpdating {
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var locations = [MKMapItem]()
@available(iOS 8.0, *)
public func updateSearchResults(for searchController: UISearchController) {
localSearch?.cancel()
localSearchRequest = MKLocalSearchRequest()
localSearchRequest.naturalLanguageQuery = searchController.searchBar.text
localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.start { (localSearchResponse, error) -> Void in
if localSearchResponse != nil {
let toNum = localSearchResponse?.mapItems.count ?? 0
for i in stride(from: 0, to: toNum, by: 1) {
self.locations.append((localSearchResponse?.mapItems[i])!)
print((localSearchResponse?.mapItems[i])!)
}
self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation(rawValue: 5)! )
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.locations.count;
}
func tableView(tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath)
let row = indexPath.row
cell.textLabel?.text = self.locations[row].name
return cell
}
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
searchController.searchBar.tintColor = UIColor(colorLiteralRed: 1, green: 1, blue: 1, alpha: 1)
searchController.searchBar.placeholder = "Location"
searchController.searchBar.returnKeyType = UIReturnKeyType(rawValue: 6)!
self.tableView.tableHeaderView = searchController.searchBar
}
override func viewDidDisappear(_ animated: Bool) {
searchController.searchBar.isHidden = true
}
}
EDIT:
Using the new localSearch.start
that vadian suggested as follows:
localSearch.start { (localSearchResponse, error) -> Void in
if let response = localSearchResponse {
self.locations.removeAll()
for mapItem in response.mapItems {
self.locations.append(mapItem)
print(mapItem)
}
if !response.mapItems.isEmpty {
let indexPaths = (0..<response.mapItems.count).map { IndexPath(row: $0, section: 0) }
self.tableView.insertRows(at: indexPaths, with: .none)
}
}
}
This still produces the same error,
attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update
.
Any help will be appreciated
Your code got two major issues:
Try something like this
Note:
UITableViewRowAnimation(rawValue: 5)!
and.none
is exactly the same, the latter is much shorter and dramatically more descriptive.But as you don't want to use row animation at all I'd recommend
Please try to reload your UITableview after fetching data from network call.
https://developer.apple.com/reference/uikit/uitableview/1614862-reloaddata
(You are inserting before the locations are fetched, and hence the tableview rows are still 0.)
Thanks Sriram