I've recently been playing around with OSX programming (usually an iOS guy) but I've hit a strange issue with NSCollectionView that I just can't seem to debug.
When I change the data that my data source uses to populate the collection with items, I call reloadData() on the collection view as usual and sometimes hits an assertion. The error I get is Parameter indexPath out of bounds or nil. If I don't change the data the app always crashes at the same point(s) though sometimes, usually the first time, it works just fine and only crashes subsequently.
Now, I've debugged this numerous times. The data is correct and at no point in my code do I ever see a nil index path. The assertion always occurs on the makeItemWithIdentifier call, and always on the last item in the collection. If I continue, I either see what I expect or else some of the cells from the previous collection are still there behind the new cells.
At one point I refactored the code slightly and found the error occurring in NSCollectionViews itemAtIndexPath: function instead.
Has anyone else seen this error and, if so, what caused it?
Update 2: I now know what is causing this issue, but have no idea how to prevent it. What happens is this: the user clicks an item in the collection view. That item changes the data object that the data source is reading from calls reloadData during the collection view delegate's didSelectItemsAtIndexPaths method. For some reason, after execution of this method, the collection view is queried again for the cell with that index path. If the table has been reloaded in the meantime then that cell is gone, leading to the exception. In short: you can't call 'reload' on a collection view while a mouse event is being processed on one of its cells without getting an annoying assertion. So if anyone can think of a way around this issue, I'd love to hear it!
Related
Considering I have a array of items which might be updated on a different view controller and get notified update the change.
How can I update a Observable<[SomeObject]> with a single SomeObject modification so the change will then be propagated to the UITableViewController that presets these items?
P.S.
I can load the whole thing again with some hack, but it's obviously wrong for various reasons.
Thanks.
The short answer is, you can't.
However, if you change your model, there are several ways you can go about doing it. One example is here: https://github.com/dtartaglia/RxMultiCounter
In RxMultiCounter, I populate the tableView with an Observable<[UUID]> and track the changes for each item inside an Observable<[UUID: SomeObject]>. Updating the latter observable doesn't cause the tableView to reload.
No, my code is not crashing by just deleting content, or reordering content, that works fine.
The issue is, the content is connected to a pusher service and it might need to delete a row at any point, even while reordering. I have been looking around for some time and I haven't found a way to:
Cancel the reordering of the cell when delete is needed (it goes
blank / clear).
Avoid any actions from a deleted cell when it finishes
'reordering'.
Tell if the table is reordering the cell before I need to
delete it.
So in short I need to delete a cell that might be reordering from a UITableView.
Have you faced a similar issue?
Anyways, I found a way to do it. Here's the logic just in case anyone ever needs it.
Prevent the cell's movement with the use of tableView:targetIndexPathForMoveFromRowAt:
On delete control don't call [yourTableView].deleteRows, call reloadData
Looks like that's it.
Thanks
I'm currently developing and iOS app in Swift 2.0 and I'm running into the following issue:
I have a custom query that fetches a list of items that populate a UITableView. When tapping the cell I get the ( values[indexPath.row] ) Object and segue it to another view controller for display as well as the list of items (for other actions like swipe to move to the next one).
My issue comes from a background process that fetches periodically new data and saves it to Realm.
Since Realm keeps all nice and updated, the indexPath.row will fetch a different value (the list of values has changed in the meantime due to the automatic updater) resulting in showing something that is not quite what was tapped.
Both Realm and the updater are working, but this results in a confusing experience for the user.
Am I missing something obvious?
Thanks a lot for the help!
PS: I've looked also at ABFRealmTableViewController, but I'm not displaying the whole data but a filtered (and ordered) subset.
Probably the easiest way of preventing this issue is to observe notifications sent out by Realm whenever a write transaction (i.e. an update) occurs and update your UI accordingly:
// Observe Realm Notifications
let token = realm.addNotificationBlock { notification, realm in
viewController.updateUI()
}
ABFRealmTableViewController supports filters via NSPredicate and sort descriptors as well. So you might want to give it another try.
i've been building an app since 1 month using NSFetchedResultsController and i was testing the app on the 3.1.2 SDK. The poblem is that i've been using NSFetchedResultsController everywhere in my app and was working on the 3.1.2 version of the SDK, now my client say that i should make it compatible with the 3.0 version and the deadline is almost there.
But is crashing everytime i change an object handled by the contoller, the application is crashing with very weird errors.
The problem occure when removing the last object in a section and when a change make an object love to another section.
I've been using a sample code from "More iPhone 3 Development Tackling iPhone SDK 3" by Dave Mark and Jeff LaMarche. I've also included some changes from link text
Here is a sample output of the console when the application is crashing.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (2 inserted, 0 deleted).'
2010-03-14 16:23:29.758 Instaproofs[5879:207] Stack: (
807902715,
7364425,
807986683,
811271572,
815059090,
815007323,
211023,
4363331,
810589786,
807635429,
810579728,
3620573,
3620227,
3614682,
3609719,
27337,
810595174,
807686849,
807683624,
839142449,
839142646,
814752238
)
If i knew that NSFetchedResultsController is so buggy, i would never used it.
So basicaly i need the my NSFetchedResultsControllerDelegate to work fine on the 3.0 and above SDKs.
It would be life saver if someone help me figure out what i'm doing wrong.
It appears from your error messages that you are inserting sections into the table when you should be deleting them. Your tableView dataSource is only supplying one section after the updates even though you have told the tableView to expect a total of four sections.
I don't think this is a case of NSFetchedResultsController being buggy, but rather that it is tricky to implement outside of simple use cases. Your crashes are almost certainly occurring as a result of your controller:didChangeObject:atIndexPath:forChangeType:newIndexPath delegate method. The key to successfully implementing this method (at least in my experience) is to keep in mind that the changeTypes are both object and indexPath driven. This makes "updates" and "moves" tricky conceptually.
Consider the situation where a managed object is changed such that it sorts under a new sectionNameKeyPath. Conceptually, we think of the object as having "moved" to a new section since the fetchedResultsController now sorts it under a new heading in the tableView. If the object's indexPath does not change, however, the fetchedResultsController considers this an "update" and not a "move".
What's worse is that even though the managed object that changed still retains the same indexPath, other objects in the fetchedResultsController may now have new indexPaths because they were bumped around by the change. This means that you will have to manually handle section insertions and section deletions in the "update" section of your delegate method. Similar problems will need to be addressed in the "move" section of your delegate method.
Without trying to explain it in so many words, LaMarche's fix is attempting to address this problem in a generic way that accommodates as many use cases as possible. By trying to understand the problem as it pertains to your use case, you may be able to significantly reduce the complexity of the code that LaMarche uses. Focus specifically on the "update" and "move" sections of your delegate method, as these are the most likely culprits for your problem.
Check out this resource:
http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html
Helped me tremendously.
I'm having a problem with a Core Data project on the iPhone. The scenario occurs when a user starts to add an object, then cancels during the process.
If the user hits cancel and returns to the list of objects, a dummy object is listed there, representing the one they were in the middle of creating. This is never saved to the database - saves occur as expected when the user hits the save button.
When the view controller where the user adds data is loaded, I create a new Thing object - this is the Core Data entity that I am adding:
myThing = [NSEntityDescription insertNewObjectForEntityForName:#"myThing" inManagedObjectContext:managedObjectContext];
I tried to delete this in my cancel method as follows:
[managedObjectContext deleteObject:myThing];
When I do this, I get a EXC_BAD_ACCESS when I hit cancel. Stepping through the code in the debugger, it gets through the cancel method fine, but this is being generated in the root view controller where I list my objects and also where I was before I tried to create this object.
All I'm trying to achieve is allowing the user to add a new object, but cancel part-way through.
Any ideas what is causing this error? I am unable to generate a stack trace from this unfortunately :(
Your approach to the object cancel is typical and appropriate.
Memory errors are common and can be tough to debug. Have you run the static analyzer? You may want to set your "myThing" reference to nil after deleting it from the context.
Do you know for sure that it is the cancel workflow that is leading to the memory error?
You can also turn on NSZombie and find out what released object is being accessed. That will help you quickly track this issue down. Google NSZombie for a few examples of how to use it.