问题
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:
- "Attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update" Error
- Others
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
回答1:
Your code got two major issues:
- Even if the number of map items is 0 one row is inserted anyway. (That caused the error).
- If there is more than one map item also only one row is inserted.
Try something like this
if let response = localSearchResponse {
for mapItem in response.mapItems { // please not those ugly C-stlye loops
self.locations.insert(mapItem, at:0)
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 )
}
}
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
if let response = localSearchResponse {
for mapItem in response.mapItems {
self.locations.append(mapItem)
print(mapItem)
}
self.tableView.reloadData()
}
回答2:
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
来源:https://stackoverflow.com/questions/41910931/cant-insert-rows-into-uitableview-swift-3