How to Catch a Nsinternalinconsistencyexception in Swift

How to Find the Source of an NSInternalInconsistencyException in an Xcode Stack Trace

This particular example doesn't give the developer much to go on. So, the answer to your question in this case is "Google it." Really, the best clue from the stack trace is the line:

[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]

The line above indicates a failed save using currentUser, combined with the error message "Tried to save an object with a pointer to a new, unsaved object." should be enough to point to a probable cause.

As it turns out, this error is not uncommon and is bewildering why Parse does not fix it. It is generally caused by when your app is using anonymous Parse users and it attempts to save an object prior to the user object having been saved. Since the user object has not been saved, it has no objectId and the save of the other object fails.

The solution is to check to see if the currentUser object has an objectId, and if not, save it first before trying to write to Parse.

    // Prevent race condition for unsaved user
// Courtesy of: http://samwize.com/2014/07/15/pitfall-with-using-anonymous-user-in-parse/
if ([PFUser currentUser].objectId == nil) {
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
//do stuff later
}];
} else {
//do stuff now
}

Swift 5.1 NSInternalInconsistencyException error

According to documentation, previousTrackCommand selector should take MPRemoteCommandEvent as first argument and return MPRemoteCommandHandlerStatus:

func addTarget(handler: (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus) -> Any

So your handlePrevTrack function should be declared as:

@objc func handlePrevTrack(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
...
}

TableView: How to proceed after catching 'NSInternalInconsistencyException'?

@synchronized(lock) solved my problem.

I just had to make sure that only one thread is able to manipulate the data source array at the same time. Now everything works fine, no more 'NSInternalInconsistencyException'.

Thx to trojanfoe and luk2302.

Exception is not being caught

Swift converts Objective-C methods with nullable returns and trailing NSError** parameters to methods that throw in Swift. But, in Objective-C, you can also throw exceptions. These are distinct from NSErrors and Swift does not catch them. In fact there is no way to catch them in Swift. You would have to write an Objective-C wrapper that catches the exception and passes it back in some way Swift can handle.

You can find this in the Apple document Handling Cocoa Errors in Swift in the Handle Exceptions in Objective-C Only section.

So it turns out that you can catch it, but it is worthwhile considering whether you should (see comments from @Sulthan below). To the best of my knowledge most Apple frameworks are not exception-safe (see: Exceptions and the Cocoa Frameworks) so you can't just catch an exception and continue on as if nothing happened. Your best bet is save what you can and exit as soon as possible. Another issue to consider is that unless you rethrow the exception, frameworks such as Crashlytics won't report it back to you. So, if you did decide to catch it you should log it and/or rethrow it so that you know that it is happening.

How to fix 'NSInternalInconsistencyException' error using UICollectionView in Swift?

Your problem is caused by all of those guard/else statements - If any of the guards fail then you return UICollectionViewCell() - Which, as the exception says, is a cell that was not dequeued correctly.

Really, your data model should have been validated before it got to this point. products should contain instances of Product rather than a Dictionary. This way you never load the invalid products into the data source array.

Once you do that you can simply write

var products: [Product]

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "productCell", for: indexPath) as! ProductCollectionViewCell

let product = products[indexPath.item]
cell.setProduct(product: product)

return cell

}

Remember that cellForItemAt: may be called many times for a given item as the collection view scrolls - It should be as efficient as possible. Although there isn't a huge overhead in accessing the dictionary and creating the Product there is no need to do it again and again.



Related Topics



Leave a reply



Submit