cs193p – Assignment #6 Task #2 Part #2

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

Recreate the user-interface from last week’s assignment but rely entirely on the above-mentioned Core Data database to present it.

Copy the files for the second table-view controller from the previous project together with the image-view controller and the flicker cache class into the current project.

Change the table view controller to be a subclass of the core-data-table-view controller, and change the public property to be a Tag entity.

@interface FlickrPhotoTVC : CoreDataTableViewController
@property (nonatomic, strong) Tag *tag;

Remove all methods for the table-view data source but the one for creating cells, and adjust it to use the Photo entity.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];    
    cell.textLabel.text = photo.title;
    cell.detailTextLabel.text = photo.subtitle;    

The method for the table-view delegate stays untouched as well as the segue method. Both methods use sendDataforIndexPath:toViewController: which needs to be adjusted for core data:

- (void)sendDataforIndexPath:(NSIndexPath *)indexPath toViewController:(UIViewController *)vc
    if ([vc respondsToSelector:@selector(setImageURL:)]) {
        [Recent recentPhoto:photo];
        [vc performSelector:@selector(setImageURL:) withObject:[NSURL URLWithString:photo.imageURL]];
        [vc performSelector:@selector(setTitle:) withObject:photo.title];

Note that in the method above, also the Recent entity is handled, for which we will create a new category shortly.

the fetched-results controller and the title of the view are setup when changing the tag (when segueing to the current view):

- (void)setTag:(Tag *)tag
    _tag = tag;
    self.title = [tag.name capitalizedString];
    [self setupFetchedResultsController];

- (void)setupFetchedResultsController
    if (self.tag.managedObjectContext) {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
        request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title"
        request.predicate = [NSPredicate predicateWithFormat:@"%@ in tags", self.tag];
        self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
    } else {
        self.fetchedResultsController = nil;

Finally create a category for the Recent entity. Check if the photo has been recently viewed. If yes, just update the entity to the current date. If not, create a new entry, check if the maximum number of entries has been reached, and delete the oldest entry if necessary.

+ (Recent *)recentPhoto:(Photo *)photo
    Recent *recent = nil;   
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Recent"];
    request.predicate = [NSPredicate predicateWithFormat:@"photo = %@", photo];
    NSError *error = nil;
    NSArray *matches = [photo.managedObjectContext executeFetchRequest:request
    if (!matches || ([matches count] > 1)) {
        // handle error
    } else if (![matches count]) {
        recent = [NSEntityDescription insertNewObjectForEntityForName:@"Recent"
        recent.photo = photo;
        recent.lastViewed = [NSDate date];
        request.predicate = nil;
        request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastViewed"
        matches = [photo.managedObjectContext executeFetchRequest:request
        if ([matches count] > RECENT_FLICKR_PHOTOS_NUMBER) {
            [photo.managedObjectContext deleteObject:[matches lastObject]];
    } else {
        recent = [matches lastObject];
        recent.lastViewed = [NSDate date];
    return recent;

The complete code is available on github.


Leave a Reply

Your email address will not be published.