Associate NSFetchedResultsController with specific section in UITableView - ios

I've got a UITableView that needs to display two sets of search results, with each set of search results being a different entity.
Each entity needs to display its search results in a specific section. I need to use an NSFetchResultsController so that if additional data becomes available the tableview automatically updates.
My question is, how do I associate a specific NSFetchedResultsController with a specific section? By this I mean I want all of the fetch results for entity 1 to be in section 0, while all of the search fetch results from entity 2 to be in section 1 of the tableview.
I've no problem having a tableview with a single section / single fetch controller, but is there anyway to have an NSFetchedResultsController be associated with a specific section of the table view?

After you set up the two NSFetchedResultsControllers, in the number of sections delegate method, specify 2 sections, for the delegate method for number of rows in a section, look at the section number and get the count from the appropriate fetched results controller, and in the cellForRowAtIndexPath: method, get the data from the appropriate fetched results controller based on the section number in the index path.

Related

Any way to group items by property in UITableView in runtime?

I have a UITableView which I populate by a list of objects I'm getting from a Realm database. What I want to do is to create sections and group items in the list by a property value in runtime.
All of the examples of grouping items in UITableView I see online are operating with it a prearranged dictionaries.
Is it possible to do?
You can set up your table view data source any way you want. You could write code that decides on the fly which items belong in which sections, but I would advise against it.
I would suggest setting up a method that takes your list of Realm objects as input, and builds an array of sections containing sub-arrays of the rows. Then your cellForRowAtIndexPath method can simply index into your model data like normal.

Batch update table row, reorder & update at the same time?

Description
I have a CoreData entry called Person, I fetch it using NSFetchedResultsController, with a fetchRequest ordered by property "name". Then I display the "name" in the table view cell.
Problem
When I change the entity's "name" property and the rows reorder, NSFetchedResultsControllerDelegate does give me a NSFetchedResultsChangeType.move. But the "name" displayed on the cell is outdated, meaning I'm not receiving NSFetchedResultsChangeType.update
The Table View Programming Guide: Inserting and Deleting Rows and Sections says batch updates do updates first, then deletions, lastly insertions.
It defers any insertions of rows or sections until after it has handled the deletions of rows or sections. The table view behaves the same way with reloading methods called inside an update blockā€”the reload takes place with respect to the indexes of rows and sections before the animation block is executed. This behavior happens regardless of the ordering of the insertion, deletion, and reloading method calls.
Question
Any idea on how the notifications sent by NSFetchedResultsController are implemented, specifically on the ordering of insert, delete, update & move?
Or how can I use some kind of code to efficiently (meaning partial update, not reload all data) solve this particular problem?
Your setup is non-standard. The sectionNameKeyPath is really meant for sections not rows. Fetch the Person entity and populate the cell with a person's name directly via itemForRowAtIndexPath.
You will then have the expected change types available.

fetchedResultsController quantity and frequency of object fetching

I am using a FetchedResultsController to fetch the data for my UITableView. The data is created via actions performed on another tab (so my table may have 5 items but if I switched tabs and go back to my table, it may have more than 5 items that it should display). My table can potentially contain many rows. Right now I am using [myFetchedResultsController performFetch] in my viewDidLoad.It appears that when I create data in my other tab, when I switch back to my table tab, that new data is put into my table automatically without me perfomring [myFetchedResultsController performFetch] again. Here are my questions:
1) Does a fetchedResultsController automatically monitor the manajedObjectContext for changes and fetches the new objects if they come into existence? (This appears to be what is happening but I just want to make sure. Perhaps I have some code that is helping me do this that I forgot I put in somewhere)
2) Does the fetch performed by [myFetchedResultsController performFetch] fetch all of the objects at that time, or does it fetch only what it can fit in the view of the table and it fetches the rest later as it needs it (as you scroll in the table)? I ask because since my table can potentially have a lot of rows, it seems inefficient to fetch all the data at once if only ~12 of them will be displayed on the table at once.
EDIT: I just realized that in my FetchedResultsController delegate methods, I have
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView reloadData];
}
Am I correct in saying that a fetchedResultsController monitors for change, but will not apply it to the table unless the table is reloaded as I have done? If so, then I have another question about UITableView. Does reloading the table only reload the rows in view and then the other rows are updated as you scroll? Again I ask because if my data is very large, it seems inefficient to reload the entire table if it will reload all rows at once.
Yes, if you add a delegate
You should set the fetch request batch size when you configure the FRC because it can only load an appropriate number of items for the screen if you tell it how many that is.
You apply the changes, the FRC just collects and supplies the data. The delegate method tells you about a change. Reloading affects the whole table in terms of row count but only shows the visible rows (assuming the batch size is set appropriately).

NSFetchedResultsController custom behavior upon empty results

I have a single section table view which is hooked up to a NSFetchedResultsController. When the results from the core data is empty and under some extra conditions I would like to create a custom row which contents will be provided not by CoreData. Is there a clean way of implementing this with the NSFetchedResultsController?
No, NSFetchedResultsController does not offer a feature like that. Just implement your table data source to check how many fetchedObjects the FRC has and use that to decide if the rows of the table should be provided by the FRC or you should instead show your custom empty row.

How do I display only a subset of a datasource in a UITableView?

I want to swap out the content of a tableview. The data source has elements with a flag that denotes whether or not they should be shown.
Ultimately, I want to be able to swap what is shown, depending on the flags. For now, though, I'll settle on an answer to the following.
How can my table display only a subset of the datasource?
I am not asking for a [tableView reload], which seems to be what most of my searches yielded. I want to show only some of the datasource items at a time based on a criteria (the flag, in this case).
As an example for clarity, here's a sample of the functionality.
We have 50 Friend elements in an array. It is the datasource for our table. When we load the app, all 50 friends are shown.
20 of those friends are marked as "Awesome" within the Friend class. When you tap the Awesome button, those 20 are shown in the table.
10 of them are marked as "Lame" within the Friend class. When you tap the Lame button, those 10 are shown in the table.
What methods do I need to look at to achieve that? TableView discussions are huge and I've been looking through bugs and errors without satisfying results, so far.
Keep two data structures. The first is the master set of data. The second contains just the data you want to display. Point the table to the second set of data.
Basically, when you want to reload the table with a different subset, create a new array, iterate the master data set and add just the objects you want to the new array.
SInce the second array just have references to the original objects from the master array, there is little extra overhead for this.
Update: To expand on the comment by Rob Napier, the master data structure I mentioned would be the "model" and the second data structure would be the data that backs the table's data source.
You can set up an NSPredicate to filter the values that will be returned by the fetchResults:
- (NSFetchedResultsController *)fetchedResults {
...
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"flag == %#", #"Awesome"];
[fetchRequest setPredicate:predicate];
...
This will only return those records that meet the criteria of the NSPredicate.

Resources