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"
                                                                  ascending:YES
                                                                   selector:@selector(localizedCaseInsensitiveCompare:)]];
        request.predicate = [NSPredicate predicateWithFormat:@"%@ in tags", self.tag];
        
        self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                            managedObjectContext:self.tag.managedObjectContext
                                                                              sectionNameKeyPath:nil
                                                                                       cacheName:nil];
    } 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
                                                                 error:&error];    
    if (!matches || ([matches count] > 1)) {
        // handle error
    } else if (![matches count]) {
        recent = [NSEntityDescription insertNewObjectForEntityForName:@"Recent"
                                               inManagedObjectContext:photo.managedObjectContext];
        recent.photo = photo;
        recent.lastViewed = [NSDate date];
        request.predicate = nil;
        request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastViewed"
                                                                  ascending:NO]];
        matches = [photo.managedObjectContext executeFetchRequest:request
                                                            error:&error];
        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.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.