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.