Update NSFetchedResultsController fetch request predicate, refresh table with animations? - ios

I cannot seem to find this laid out anywhere.
I have what is effectively a search box (though it's using a UITextView, not a search box/controller).
As the user types in words, I want to update the 'suggestions' in the table view below that are pulled from Core Data. These are displayed in a table below using the typical NSFRC setup.
After the user types (and with a delay of .5s) I update the fetch request predicate with their text, and call performFetch again.
What I really want is the new results to animate in, as you would normally see with NSFRC, of course leaving any existing matching rows in place. Currently the only way I get these to update is by calling reloadData on the table.
Is there a way to get what I'm after here?

Related

NSManagedObjectContext refreshObject causes duplicates in NSFetchedResultsController

I have an issue where if I make changes to a core data object, save then refreshing the object, causes my NSFetchedResultsController to show a duplicate object. I think I understand what's going on, but I'm looking for someone to confirm, and also to hopefully give some more detail as to why.
To explain in more dtail I have two entities, Fixture and Position. A Fixture has many Positions, and a Position belongs to only one Fixture. To reproduce the issue I do the following:
Fetch all Positions.
Modify some value (any one) on that objects Fixture. I.E foo.fixture.name = "foobar"
Save the context
Refresh objects by calling context.refreshAllObjects, or context.refreshObject(foo, mergeChanges: false/true).
I have a tableview using a fetched results controller which displays Fixures. After doing the above the tableview will display duplicates for each item (it doesn't matter if I use the delegate methods of the FRC to do the update or I just reload the tableview).
It appears what's happening is that the refresh invalidates the objects that the FRC knows about, while at the same time gets knowledge of another set of objects. If, as step #5, I call frc.performFetch() then the problem goes away.
Other things to note:
No matter how many times I run the code I only get two of each object (I'm using a random button to trigger it for testing).
init(entityName, context) is called on my Fixture subclass as soon as I access the Fixture property of my object during the next code run (i.e after refresh was called).
In my sample everything is taking place on the same context (though it happens with child contexts as well)
To give some more context as to how I got myself in this situation in the first place users can click on a fixture in the list and then ultimately narrow down on a single position a few screens later where they can perform actions that modify the fixture. There are other active areas of the application at this point that are listening to the NSManagedObjectContextDidSaveNotification and I want them to update their objects so they can display the correct data, which is why I was calling refresh.
I've dug around in the docs and I can't see anything that specifically explains my theory that updating the context causes NSFetchedResultsController to have invalid objects. Can anyone shed some light on this behavior?
First, you really should not be overriding -init... on a NSManagedObject. That is one of the methods that you are strongly discouraged from overriding and can very easily be the source of your issues.
Second, your entire UI should be using a single instance of the NSManagedObjectContext that is associated to the main queue and therefore there should only be ONE instance of any particular entity in your UI. If you have multiple contexts you are just making things more complicated for yourself. If you are using a single context keep in mind that no matter how many times you fetch an object against that context you will get the exact same pointer back.
The NSFetchedResultsController will never create objects, it only fetches and provides them for display. Therefore the NSFetchedResultsController is only reporting the fact that you have created this duplication somewhere else in your code.
Now some questions, do these duplicates get pushed down to disk?
Can you see them in the store file on disk?
When you re-launch your application are the duplicates still there?
When you put a print in your custom -init methods on the NSManagedObject; do they fire more than once?

Realm over CoreData should I use NSFetchedResultController or a Dictionary?

I'm working on an app using Core Data and NSFetchedResultController but for many reasons I would like to switch it to use Realm.
I saw that there is a "Realm version" of the NSFetchedResultController on github but It wouldn't be compatible with my current code using Core Data.
The view controller is displaying a list of People from the same school, like an address book.
This list is a sublist of a people who studied in the same city.
So I was thinking to make 1 unique request to the database to retrieve the list of all people and then filter locally this list within 1 Dictionary per school [String: AnyObject] with String as Section name within the tableView and AnyObject an array of people.
first solution, make a NSFetchedResultController for each school with a predicate filtering the location. Then all delete actions etc.. are handled by the delegates -> this is not compatible with Realm
Create those dictionaries and update them for each actions... -> this works with Realm but it's very annoying to code.
Any better solution?
EDIT:
I need to clarify my request:
I'd like to write a class that inherit UITableViewController.
This class has a list of people sorted in the alphabetical order
The tableview has section with the first letter of their firstname
The tableview controller needs to handle updates of the data model (insert, update, delete)
As we might move from CoreData to Realm, I'd like to write code that is compatible with both so that I don't need to modify it again later. The only "smart" way I found to do it so far is to forget about the NSFetchedResultController and the RBQFetchedResultsController, because they are respectively linked to CoreData and Realm, and then use data structure like Dictionaries.
Just to clarify, you're creating a UITableView with multiple sections; 1 per school, and you want to sort a flat list of people in a Realm database into the table based on their school, correct?
If that Realm fetched results controller you mentioned (I'm guessing it's RBQFetchedResultsController) doesn't fit your app's architecture, then yeah, dictionaries would be the way to go, but it shouldn't hopefully be as 'manual' as you'd think.
The good thing about Realm Results objects are that they are 'live' in the sense that if a new item is added to Realm after the Results query was made, it'll be retroactively updated to include the new item. That being the case, as long as you're managing a dictionary of Results objects that each relate to fetching the people for each specific school, the only manual aspect would be managing the table sections themselves.
The only thing to be aware of is you'll need a mechanism to be notified when a new person has been added to a specific school (in order to know to refresh that section of the table view), but for now, it would be best if you did that in your own logic (Either through a callback block, or a delegate call).
On a sidenote, we're in the middle of adding a set of new APIs to make implementing native fetched results controller behaviour possible in Realm (i.e., automating the need to post a notification when a new object is added). We haven't got a proper release date confirmed yet, but it should be within the first quarter of 2016! :)

Notification when UITableView changes

I often have a UITableViewController with an edit button, which I like to disable when there are no rows in the table. To keep this in sync, I enable/disable the button every time something happens that might update its dataSource - adding the first row, deleting the last row, in viewDidLoad, etc. Whenever I add some new functionality that can affect the contents of the table, I have to remember to incorporate this logic.
Is there some delegate of the UITableView that I can use to simplify this? A way to know whenever the table (or it's dataSource) is modified, where I can check the number of items in the dataSource and enable/disable accordingly.
Alternatively, any other approaches would be welcomed.
You are the data source. So you do know whenever the data source changes, if you care to know. In other words, the reason you're having this problem is that you're treating the model (in the model-view-controller architecture) as an alien being. Instead, treat the model as something of your own. Take charge of your model. For example, is the model an array? Then wrap it in a class of your own, to which all commands to change the array must be given. That way, it can emit a notification whenever it is told to change the array.
It is also possible under certain circumstances to use Key-Value Observing to get notified when something changes, and you could look into it, but with primitives like arrays and dictionaries it is possible that this will be more trouble than it's worth. Again, you're likely to be happier wrapping your model storage in your own class, whose observability via KVO you can manage yourself.

How do I Handle NSFetchedResultsControllerDelegate updates for custom results view

I am currently working on a CoreData based iPhone app with a map view that will have its annotations generated from an NSFetchedResultsController. The idea of the map view is that it will show a number of saved locations for the user.
One of the advantages of using an NSFetchedResultsController is that I can set my map view as a delegate on NSFetchedResultsController and get notified of any changes made to the set of saved locations that happen on another device or on a website when the user is logged in.
I am currently having a bit of trouble getting my head around how to deal with a number of different kinds of updates that are sent to my NSFetchedResultsControllerDelegate implementation. The documentation: http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html doesn't seem to tell you how these different updates should be handled as it seems more geared towards integrating with a UITableView, which does most of the work.
I am keeping an NSDictionary of my annotations that maps them to the NSIndexPath inside the result set. The issue is, for example, when I receive 10 move, 3 insert and 4 delete updates, what order should I process these in? Some of these indexPaths will have a number of conflicting indices and the order in which they are processed will have an affect on the actual annotations I need to move, insert or delete. If I perform all the move updates first, then the insert indices will cause the final order to be different to their final order if I inserted first.
Are there any existing small libraries/classes that will translate a set of indices prior to an update to a set of post update indices given those update messages? If not, can anyone explain how this stuff works so I can write my own?
Any help will be greatly appreciated!
The flow of the NSFetchedResultsControllerDelegate methods for one update cycle is like this:
controllerWillChangeContent: (called once)
controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: (called X times)
controllerDidChangeContent: (called once)
Every call to the didChangeObject method will be about just one object / indexPath. You should apply the changes in the order that you receive them via those calls to didChangeObject. That will keep them consistent.
If you are using sections, you could also have calls to controller:didChangeSection:atIndex:forChangeType: intermixed with the object changed calls.

Web App Saving Entire Table At Once

Set the scene:
New to .NET; drinking from firehose
ASP.NET MVC app, SQL Server back
Editable table in browser with a single SAVE button.
User can right-click to add or delete rows.
Table won't ever have more than approx. 30 rows.
My question :
I'm saving everything upon the Save button click but would it be better to save row by row, AJAX style, as the user makes updates?
I don't like the look of separate buttons for each row, which is why I've designed it this way.
Is this mostly a UI issue? Am I missing any technical gotchas here, such as backend failure during the mass saving of the rows?
Additionally, assume I do save the entire table at once, is it better to create an ADO DataTable object or just loop through, inserting/updating each row as I go by calling a stored procedure. I suppose I could add LINQ to the firehose, but that would make this question even less "answerable".
You don't have a huge volume of data here, so saving all 30 rows at the end of the table is a reasonable approach. But you should be prepared for a failure, particularly if you are changing existing rows when it will fail more often due to other apps/users changing the same data. Just make sure that you wait for confirmation from the SQL server that the changes have been committed.
What I've done before with these sorts of big table views is when somebody clicks on a cell they'd like to edit, run some ajax to display a text field with that text, they can edit, then listen to onmouseout and the enter button to send off the ajax request to modify the single row.
When the response from the ajax call comes back you can add a tooltip or something that it was saved, and then change the cell to the new val.
Assuming you have SQL2005, you could build up an XML document with all of your data rows, then call a single stored proc and pass it your XML. Then the stored proc could save all of the rows at once.

Resources