iPhone Developer : Using Core Data for a Table Data Source

9/18/2012 1:13:35 AM
Core Data on the iPhone works closely with table views. The NSFetchedResultsController class includes features that simplify the integration of Core Data objects with table data sources. As you can see in the following list, many of the fetched results class’s properties and methods are designed for table support.
  • Index path access— The fetched results class offers object-index path integration in two directions. You can recover objects from a fetched object array using index paths by calling objectAtIndexPath:. You can query for the index path associated with a fetched object by calling indexPathForObject:. These two methods work with both sectioned tables and those tables that are flat—that is, that only use a single section for all their data.

  • Section key path— The sectionNameKeyPath property links a managed object attribute to section names. This property helps determine which section each managed object belongs to. You can set this property directly at any time or you initialize it when you set up your fetched results controller.

    Recipe 19-1 uses an attribute named section to distinguish sections, although you can use any attribute name for this key path. For this example, this attribute uses the first character of each object name to assign a managed object to a section. Set the key path to nil to produce a flat table without sections.

  • Section groups— Recover section subgroups with the sections property. This property returns an array of sections, each of which stores the managed objects whose section attribute maps to the same letter.

    Each returned section implements the NSFetchedResultsSectionInfo protocol. This protocol ensures that sections can report their objects and numberOfObjects, their name, and an indexTitle, that is, the title that appears on the quick reference index optionally shown above and at the right of the table.

  • Index titles— The sectionIndexTitles property generates a list of section titles from the sections within the fetched data. For Recipe 19-1, that array includes single letter titles. The default implementation uses the value of each section key to return a list of all known sections.

    Two further instance methods, sectionIndexTitleForSectionName: and sectionForSectionIndexTitle:atIndex:, provide section title lookup features. The first returns a title for a section name. The second looks up a section via its title. Override these to use section titles that do not match the data stored in the section name key.

The code in this recipe recovers data from the fetched results using index paths, as shown in the method that produces a cell for a given row and the method that tints the navigation bar with the color from the selected row.

Each method used for creating and managing sections is tiny. The built-in Core Data access features reduce these methods to one or two lines each. That’s because all the work in creating and accessing the sections is handed over directly to Core Data. The call that initializes each fetched data request specifies what data attribute to use for the sections. Core Data then takes over and does the rest of the work.

self.fetchedResultsController = [[NSFetchedResultsController alloc]
    sectionNameKeyPath:@"section" cacheName:@"Root"];

Caching reduces overhead associated with producing data that’s structured with sections and indices. Multiple fetch requests are ignored when the data has not changed, minimizing the cost associated with fetch requests over the lifetime of an application. The name used for the cache is completely arbitrary. Either use nil to prevent caching or supply a name in the form of an NSString. The snippet above uses "Root", but there’s no reason you can’t use another string.

Recipe 1. Building a Sectioned Table with Core Data
- (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath
    // Retrieve or create a cell
    UITableViewCell *cell =
        [tableView dequeueReusableCellWithIdentifier:@"basic cell"];
    if (!cell) cell = [[[UITableViewCell alloc]
        reuseIdentifier:@"basic cell"] autorelease];

    // Recover object from fetched results
    NSManagedObject *managedObject =
        [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [managedObject valueForKey:@"name"];
    UIColor *color =
        [self getColor:[managedObject valueForKey:@"color"]];
    cell.textLabel.textColor =
        ([[managedObject valueForKey:@"color"] hasPrefix:@"FFFFFF"]) ?
            [UIColor blackColor] : color;

    return cell;

- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    // When a row is selected, color the navigation bar accordingly
    NSManagedObject *managedObject =
        [self.fetchedResultsController objectAtIndexPath:indexPath];
    UIColor *color =
        [self getColor:[managedObject valueForKey:@"color"]];
    self.navigationController.navigationBar.tintColor = color;

#pragma mark Sections
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    // Use the fetched results section count
    return [[self.fetchedResultsController sections] count];
- (NSInteger)tableView:(UITableView *)tableView
    // Return the count for each section
    return [[[self.fetchedResultsController sections]
        objectAtIndex:section] numberOfObjects];

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView
    // Return the array of section index titles
    return self.fetchedResultsController.sectionIndexTitles;

- (NSString *)tableView:(UITableView *)aTableView
    // Return the title for a given section
    NSArray *titles = [self.fetchedResultsController
    if (titles.count <= section) return @"Error";
    return [titles objectAtIndex:section];

- (NSInteger)tableView:(UITableView *)tableView
    sectionForSectionIndexTitle:(NSString *)title
    // Query the titles for the section associated with an index title
    return [self.fetchedResultsController.sectionIndexTitles

  •  Anita Mai Tan - The Container Is Worth More Than The Contents
  •  No New Toaster – Refrigerators
  •  The State Of Mobile... Creative Media In 2012 (Part 2)
  •  The State Of Mobile... Creative Media In 2012 (Part 1)
  •  A Not So New Competitor
  •  BlackBerry Java Application : installing the Java Development Kit (JDK), downloading Eclipse with the JDE plugin
  •  BlackBerry Java Application : Installing the Development Environment - downloading the Java Development Kit
  •  iOS 6 Playing It Safe (Part 1)
  •  iOS 6 Playing It Safe (Part 2)
  •  Planet Of The Apps – Travel (Part 1)
  •  Planet Of The Apps – Travel (Part 2)
  •  Planet Of The Apps – Travel (Part 3)
  •  Top 10 Smartphones August – September (Part 1) - Samsung Galaxy S III, HTC One X, Apple iPhone 4S,Nokia Lumia 800,Sony Xperia S
  •  Top 10 Smartphones August – September (Part 2) - Huawei Ascend P1, HTC Radar, Samsung Galaxy Note,BlackBerry Bold 9900
  •  Got Yourself A Fancy New Nexus Flexus
  •  Nokia 808 Pureview - Best For Convergists
  •  Tough Phones : Work or play in harsh environments
  •  Take Your Office On The Go
  •  Tablets For All Budgets (Part 3) - Apple New iPad, Asus Transformer Infinity TF700
  •  Tablets For All Budgets (Part 2) - Samsung Galaxy Tab 7.7, Apple iPad 2, Samsung Galaxy Tab 2, Acer Iconia Tab A700
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    20 Ice Cream Sandwich Secret Revealed! (Part 1)
    Quad Gods - The Mobile Chip Race Is Beginning
    Asus GeForce GTX 690 - SLI speeds on a single card
    SharePoint 2010 : SQL Backup Tools
    Mobile - A Challenger Appears
    How To Get The Best From Your Batteries (Part 2)
    Windows Phone 7 Development : Push Notifications - Implementing Cloud Service to Track Push Notifications
    Windows Server 2008 and Windows Vista : Administering GPOs (part 2) - Starter GPOs
    SharePoint 2010 : Workflow Modeling and Development Tools (part 2) - Visual Studio 2010 & Workflow Modeling Tools Comparison
    Enhancing Your Digital Life From The Desktop To Your Mobile (Part 3)
    Performance Management Tools in SQL Server 2008
    Exploring an Assembly Using ildasm.exe
    Windows 8 Storage Spaces (Part 1)
    Business Software Releases & Update – December 2012
    The Outer RIM (Part 1)
    Building Out Of Browser Silverlight Applications - Using COM Interoperability and File System Access
    Oracle Database 11g : Installing Oracle - Research and Plan the Installation
    Lenco iPT-223
    Windows Server 2003 : Configuring a Windows IPSec Policy (part 4) - Using Group Policy to Implement IPSec, Monitoring and Troubleshooting IPSec
    Beginning Android 3 : Working with Containers - Tabula Rasa