cs193p – Assignment #6 Part #9

Please note, this blog entry is from a previous course. You might want to check out the current one.

Photos Table & Image View

Assignment #6 Task #4

When a region is chosen, all the photos in your database that were taken in that region should be displayed (no sections are required). When a photo is then chosen, it should be displayed in the same way photos were displayed in last week’s assignment.

Like in the last part, clear out the generic photo-table-view controller. For now it needs only a single method to setup the table cells using the photo data:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Photo Cell"];
    
    Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = photo.title;
    cell.detailTextLabel.text = photo.subtitle;
    
    return cell;
}

Refactor the place-photos-table-view controller to a region-photos-table-view controller. Remove all its properties and methods … Instead, add a single public property to hold the current region:

@property (nonatomic, strong) Region *region;

When the region is set, setup the fetched-results controller:

- (void)setRegion:(Region *)region
{
    _region = region;
    self.title = region.name;
    [self setupFetchedResultsController];
}

Get the managed-object context from the current region. Using the region as predicate might produce a problem when we delete the region in the background (remember my region category does that …), thus looking for the regions name generates more stable results:

- (void)setupFetchedResultsController
{
    NSManagedObjectContext *context = self.region.managedObjectContext;
    if (context) {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
        request.predicate = [NSPredicate predicateWithFormat:@"region = %@ OR region.name = %@", self.region, self.region.name];
        request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title"
                                                                  ascending:YES
                                                                   selector:@selector(localizedStandardCompare:)]];
        
        self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                            managedObjectContext:context
                                                                              sectionNameKeyPath:nil
                                                                                       cacheName:nil];
    } else {
        self.fetchedResultsController = nil;
    }
}

… and the regions-table-view controller needs to provide the region to the photos-table-view controller:

- (void)prepareViewController:(id)vc
                     forSegue:(NSString *)segueIdentifer
                fromIndexPath:(NSIndexPath *)indexPath
{
    Region *region = [self.fetchedResultsController objectAtIndexPath:indexPath];
    if ([vc isKindOfClass:[RegionPhotosTVC class]]) {
        RegionPhotosTVC *rpTVC = (RegionPhotosTVC *)vc;
        rpTVC.region = region;
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue
                 sender:(id)sender
{
    NSIndexPath *indexPath = nil;
    if ([sender isKindOfClass:[UITableViewCell class]]) {
        indexPath = [self.tableView indexPathForCell:sender];
    }
    [self prepareViewController:segue.destinationViewController
                       forSegue:segue.identifier
                  fromIndexPath:indexPath];
}

… at the current state the code will not run. We changed the generic photos-table-view controller which is also used by the recent-photos-table-view controller … This one is not able to handle Core Data yet … Disable it by commenting out or removing the following line:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
//	self.photos = [RecentPhotos allPhotos];
}

To show the photo in the photo view, hand over its URL via a helper method while preparing the segue (for the iPhone) and from the table delegate (for the iPad):

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    id detailvc = [self.splitViewController.viewControllers lastObject];
    if ([detailvc isKindOfClass:[UINavigationController class]]) {
        detailvc = [((UINavigationController *)detailvc).viewControllers firstObject];
        [self prepareViewController:detailvc
                           forSegue:nil
                      fromIndexPath:indexPath];
    }
}

- (void)prepareViewController:(id)vc
                     forSegue:(NSString *)segueIdentifer
                fromIndexPath:(NSIndexPath *)indexPath
{
    Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];    
    if ([vc isKindOfClass:[ImageVC class]]) {
        ImageVC *ivc = (ImageVC *)vc;
        ivc.imageURL = [NSURL URLWithString:photo.imageURL];
        ivc.title = photo.title;
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSIndexPath *indexPath = nil;
    if ([sender isKindOfClass:[UITableViewCell class]]) {
        indexPath = [self.tableView indexPathForCell:sender];
    }
    [self prepareViewController:segue.destinationViewController
                       forSegue:segue.identifier
                  fromIndexPath:indexPath];
}
cs193p – assignment #6 task #1 - show image
show image

The complete code for tasks #1 to #7 is available on github.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

3 thoughts on “cs193p – Assignment #6 Part #9”

  1. We can retrieve the managedObjectContext from the core Data instance?

    self.region.managedObjectContext is legal?

Leave a Reply

Your email address will not be published.