简体   繁体   中英

iOS Core Data - Design Pattern for Passing Context to Detail Views

I'm a little stumped with an issue that I think goes back to my design.

I'm constructing a TableViewController based on a mainly static set of rows (4) - using that as a basis for a UITableView. Each row will kick off varying different views (detail, and UITableViews)... In my managed object context for the top view I can easily nav to the associated detail view because it's in context (nickname).. I initially thought about simply having unrelated tables and a series of buttons that would fire off the views... But I ditched that idea. My main current issue is knowing how to switch MOC or to different fetchedresults controllers (which are by the way defined in each .m to fetch from different tables.

At the moment, I've got a switch inside of TableViewControler.m.. This snipit works:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSInteger switchval = indexPath.row;

    switch (switchval) {
     case 0: // Nickname 
     {
       //This version brings up a detailed view controller - 
      NickNameDetail *controller = [[NickNameDetail alloc] initWithNibName:@"NickNameDetail" bundle:nil];
      controller.fetchedResultsController = self.fetchedResultsController;
      controller.managedObjectContext = [self.fetchedResultsController objectAtIndexPath:indexPath];
      [self.navigationController pushViewController:controller animated:YES];
      break;  
     }
     case 1:  
     {      
      //NextTableViewContoller *.... (etc)... here here
    ...

However, I can't figure out how to switch to a different context and get different rows.

meTableViewController.managedObjectContext = self.managedObjectContext;
nickNameDetail.managedObjectContext = self.managedObjectContext;
nextTableViewController.managedObjectContext = self.managedObjectContext;

Anyone run into a scenario like this before? Sorry, can't get the code formatter to behave.

Thanks!

In some cases it may be good/opportune to pass to the new view controller pushed on the navigation stack the MOC of your current view controller. However, you usually want to pass a newly created MOC. Do this as follows:

in your app delegate add the following method

- (NSManagedObjectContext*)createNewManagedObjectContext
{

    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[self persistentStoreCoordinator]]; 
    return [moc autorelease];
}

in your view controller pass the MOC as follows

myAppDelegate *mainDelegate = (myAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainMOC = [mainDelegate createNewManagedObjectContext]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) 
                                                         name:NSManagedObjectContextDidSaveNotification
                                                       object:mainMOC];

newViewController.managedObjectContext = mainMOC;

and then handle the notification as needed, here is an example

- (void)contextDidSave:(NSNotification *)notification
{

    [managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    [self.tableView reloadData];

}

You also need to define and use a different NSFetchedResultsController for each of your view controllers. This is because the data you want to fetch and display are, of course, different for each view controller (different entity, predicate etc). Simply define them in each implementation file. Here is an example:

- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
     */

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Context" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    if(self.project){
        // get the contexts for the project
        NSPredicate * predicate = [NSPredicate predicateWithFormat: @"projectName == %@", self.project.name];
        [request setPredicate:predicate];
    }

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];


    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [request release];
    [sortDescriptor release];
    [sortDescriptors release];

    return fetchedResultsController;
}    

and then use the fetchedResultsController as needed. For instance, put this in your viewDidLoad method:

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM