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];
}

The complete code for tasks #1 to #7 is available on github.
We can retrieve the managedObjectContext from the core Data instance?
self.region.managedObjectContext is legal?
It is part of the lectures, thus it’s at least legal in the US ;=)
Great!