Jamie McAllister Jamie McAllister - 2 months ago 6
Swift Question

Not sure how to fix NSInconsistencyException

A brief description of the app first:

The app is intended to display a list of dogs and indicate whether or not they are currently in the building (for a doggy day care company). The user adds a dog by searching for it. The app gets these dogs from a database.

I had this working at one point. However I had an error about auto layout running on a background thread. I googled it and found this line:

dispatch_async(dispatch_get_main_queue(), {})
which fixes the error.

the problem is now I have an
NSInconsistencyException
.

The function causing the error:

func searchFor(){
//print(searchBar.text)
let url = NSURL(string: "http://192.168.0.8/classes/main.php?fn=dogSearch&s=" + searchBar.text!)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
print(NSString(data: data!, encoding: NSUTF8StringEncoding))
//var boardings = [String]()
self.dogs.removeAll()
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as! [AnyObject]

if let theDogs = json as? [[String: AnyObject]] {
for dog in theDogs {
if let ID = dog["ID"] as? String {
print(ID + " Safe")
let thisDog = Dog(name: (dog["Name"] as? String)!, surname: (dog["Surname"] as? String)!, id: (dog["ID"] as? String)!, boarding: false)
let newIndexPath = NSIndexPath(forRow: self.dogs.count, inSection: 0)
self.dogs.append(thisDog)
dispatch_async(dispatch_get_main_queue(), {
// code here
self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
})
}
}
}
} catch {
print("error serializing JSON: \(error)")
}

// print(names) // ["Bloxus test", "Manila Test"]

}

task.resume()
}


the error:


*** Assertion failure in -[UITableView _endCellAnimationsWithContext:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-
3512.60.7/UITableView.m:1716

2016-09-08 21:56:27.559 Day Care Register[1961:654300]
*** Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 0. The number of rows contained in an
existing section after the update (3) must be equal to the number of
rows contained in that section before the update (0), plus or minus the
number of rows inserted or deleted from that section (1 inserted, 0
deleted) and plus or minus the number of rows moved into or out of that
section (0 moved in, 0 moved out).'


If I understand that right, it's telling me the function is adding
Dog
s to the array faster than it's creating the rows for the table?

Can anyone help me resolve this?

Answer

UITableView will throw an exception if the array that you provide to it isn't the same size as it as you're updating it.

To prevent this, wrap your code inside beginUpdates() and endUpdates() calls, so that when you've finished appending the dogs to your array you've also added all your rows to the table within the same batch.

Try putting the entire operation on the main queue and wrapping it in these update calls like so:

dispatch_async(dispatch_get_main_queue(), {
    self.tableView.beginUpdates()
    if let theDogs = json as? [[String: AnyObject]] {
        for dog in theDogs {
            if let ID = dog["ID"] as? String {
                print(ID + " Safe")
                let thisDog = Dog(name: (dog["Name"] as? String)!, surname: (dog["Surname"] as? String)!, id: (dog["ID"]  as? String)!, boarding: false)
                let newIndexPath = NSIndexPath(forRow: self.dogs.count, inSection: 0)
                self.dogs.append(thisDog)


                self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
            }
        }
    }
    self.tableView.endUpdates()
})
Comments