Please note, this blog entry is from a previous course. You might want to check out the current one.
Have a row in your main table view called “All” which shows all the photos (not just the photos with a certain tag). Then have the table that appears when you click on “All” be divided into sections by tag (i.e., each section is one of the tags). The simplest way to add the “All” row is to update the information in your database a little bit rather than trying to special-case your table view code (though you will need a special case to turn on sections for that particular table of all photos since you don’t want other tables of photos to have sections). Luckily “All” is alphabetically at the top of the list of types of places, but can you think of a way to modify your schema/fetch criteria to ensure that it is always the top item in the list even if it’s not called “All” or if there were an “Abattoir” tag in the list?
Just add an additional tag for “All” to all photos. To circumvent to “Abattoir” sorting problem, name it so that it will be always be first, e.g.:
#define ALL_TAGS_STRING @"00000" ... + (NSSet *)tagsFromFlickrInfo:(NSDictionary *)photoDictionary inManagedObjectContext:(NSManagedObjectContext *)context { ... tagStrings = [tagStrings arrayByAddingObject:ALL_TAGS_STRING]; ... }
… because it is not named “All” it needs to be rewritten when used:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { ... if ([tag.name isEqualToString:ALL_TAGS_STRING]) { cell.textLabel.text = @"All"; } else { cell.textLabel.text = [tag.name capitalizedString]; } ... } ... - (void)setTag:(Tag *)tag { ... if ([tag.name isEqualToString:ALL_TAGS_STRING]) { self.title = @"All"; } else { self.title = [tag.name capitalizedString]; } ... }
To be able to sort all photos according to its tags, add a new attribute to the Photo entity, which holds the name of the first tag (sorted alphabetically):
+ (Photo *)photoWithFlickrInfo:(NSDictionary *)photoDictionary inManagedObjectContext:(NSManagedObjectContext *)context { ... NSArray *tags = [[photo.tags allObjects] sortedArrayUsingComparator:^NSComparisonResult(Tag *tag1, Tag *tag2) { return [tag1.name compare:tag2.name]; }]; photo.tagsString = [((Tag *)tags[1]).name capitalizedString]; ... }
When setting up the fetched-results controller, check if a specific tag is shown or all photos, and change the sorting & section accordingly. Note the following code uses two sorting descriptors. First sort for the sections, then the photo names alphabetically:
- (void)setupFetchedResultsController { ... NSString *sectionNameKeyPath = @"firstLetter"; if ([self.tag.name isEqualToString:ALL_TAGS_STRING]) { request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"tagsString" ascending:YES], [request.sortDescriptors lastObject]]; sectionNameKeyPath = @"tagsString"; } ... self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.tag.managedObjectContext sectionNameKeyPath:sectionNameKeyPath cacheName:nil]; ... }
The complete code is available on github.
Hi,
A couple of photos have several categories (classroom & engineering for example). This doesn’t seem to be managed in your code: a photo is listed in one and only one category.
Besides that, great site and great code 🙂
Regards,
Florian