Reputation: 1968
Take a look at the Music.app (or iPod.app). The root Albums view has an "All Songs" row. The root Songs view has a "Shuffle" row. The root Playlists view has an "Add Playlist..." row. Static data mixed in the same UITableView with (presumably) Core Data data. I'm wondering how Apple achieved this.
I've tried two different approaches, both failed. Like the Music.app, my views also have a UISeachBar in the tableHeaderView. My first attempt kept track of how many "static" rows I had and adjusted the indexPath provided to the various UITableView and NSFetchedResultsController methods that require section and row info. Everything was working great until I implemented the NSFetchedResultsControllerDelegate methods to allow creating, editing and deleting. The insertRowsAtIndexPaths:withRowAnimation:
method (and similar) gets tripped up on my adjusted indexPaths. The default indexPaths don't work as is either.
My second attempt was to nest another UITableView in the tableHeaderView of my primary UITableView to use for the static rows (and to house the UISeachBar in it's own tableHeaderView). This approach didn't even make it to the editable stage. The UISearchBar ends up being overlapped by the root UITableView's sectionIndex scrubber and no longer slides up behind the UINavigationBar when scrolling a short list.
So rather than diagnose my specific problems I'm asking for suggestions on how Apple achieves this. Could they be fetching the data once, caching it in an NSArray and constructing a nested NSArray of sections and rows that includes both the static and Core Data rows?
Upvotes: 5
Views: 777
Reputation: 1605
That's what I would do (build my own cache). The wrinkle in your app vs. iPod.app seems to be the NSFetchedResultsControllerDelegate bit. I don't think iPod.app offers that particular interface, right? So, no automagical create/edit/reorder support.
As you yourself stated, it was adding that in that caused your indexPath munging to stop working.
I think you'll just have to hand roll this. This seems pretty typical of Apple's APIs: once you deviate from the straightforward use cases, their convenience functionality starts running into issues. You should file bugs in bugreport suggesting how you would like this to work -- hopefully they'll come up with something in the future, since this seems like a use case that others might run into.
Also, I don't know if you need to go all the way to storing in NSArrays, but if you do, page out your fetches and only cache what's necessary in RAM if the set can get really large.
I have a simple photo app I'm working on and the cache is backed by something that effectively works like a cursor. For now, I do end up keeping everything in memory, too, but the details are hidden behind an interface that I'll be able to refactor pretty easily. The interface looks like an array, but automatically knows to go to the network to fetch additional results sets, cache them to CoreData, and mix results from different pages. So, my UITableView delegate just does [cursor objectAtIndex:blah] and the magic is hidden behind the scenes. It's very doable.
Sujal
Upvotes: 1
Reputation: 195
I ran into this same problem recently. I wanted to add a row at the top of the table with some static content (All Songs). I got around the issue by simply inserting my own section for section 0, and then incrementing the core data sections. 0 becomes 1, 1 becomes 2, etc.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_fetchedResultsController sections] + 1;
}
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
if( section == 0 ) {
return 1;
}
id <NSFetchedResultsSectionInfo> sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section-1];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// All Charts
if( indexPath.section == 0 && indexPath.row == 0 ) {
// Set up the custom cell
}
// Sets
else {
// Set up the core data cells
}
}
The rest is just a matter of adjusting the indexPath sections when removing rows and the like.
Upvotes: 3