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!