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.