cs193p – Assignment #4 Task #3 & #7

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

The main (non-Recents) tab must present a list containing all of the tags (FLICKR_TAGS) on all of the photos queried except the tags “cs193pspot,” “portrait” & “landscape” (note that Flickr tags come back all lower case with no special characters). The subtitle for each cell in this list should display how many photos have the corresponding tag. Capitalize the tags so they look a bit nicer in the list.

All lists should each be displayed in a UITableView.

Create a new UITableViewController sub class. The model of the controller needs two properties. An array to store the photos received from Flickr and a dictionary where those photos are sorted by its tags:

@property (nonatomic, strong) NSArray *photos; // of NSDictionary
@property (nonatomic, strong) NSDictionary *photosByTag; // of NSArray of NSDictionary

The photos are loaded in viewDidLoad:

- (void)viewDidLoad
    [super viewDidLoad];
    self.photos = [FlickrFetcher stanfordPhotos];

When setting the photos call a helper method to generate the tags dictionary and reload the table:

- (void)setPhotos:(NSArray *)photos
    _photos = photos;
    [self updatePhotosByTag];
    [self.tableView reloadData];

In this helper method loop over all photos. Generate an array from the tags string and loop over this array as well. For the three “bad” tags do nothing. Otherwise check if the tag already exists, and create a new array if not. Then add the current photo. Finally set the property with the generated dictionary:

- (void)updatePhotosByTag
    NSMutableDictionary *photosByTag = [NSMutableDictionary dictionary];
    for (NSDictionary *photo in self.photos) {
        for (NSString *tag in [photo[FLICKR_TAGS] componentsSeparatedByString:@" "]) {
            if ([tag isEqualToString:@"cs193pspot"]) continue;
            if ([tag isEqualToString:@"portrait"]) continue;
            if ([tag isEqualToString:@"landscape"]) continue;
            NSMutableArray *photos = [photosByTag objectForKey:tag];
            if (!photos) {
                photos = [NSMutableArray array];
                photosByTag[tag] = photos;
            [photos addObject:photo];
    self.photosByTag = photosByTag;

The number of sections in the table is one, the number of rows equals the number of tags:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    return 1;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    return [self.photosByTag count];

The title of the rows is derived from the keys of the dictionary, the subtitle from the count of its contents:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    static NSString *CellIdentifier = @"Tag Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier 
    NSString *tag = [[self.photosByTag allKeys] objectAtIndex:indexPath.row];
    int photoCount = [self.photosByTag[tag] count];
    cell.textLabel.text = [tag capitalizedString];
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%d photo%@", photoCount, photoCount > 1 ? @"s" : @""];    
    return cell;

Finally exchange the first (top) view controller for a table-view controller. Set its class to use the newly created class from above. Set the cell type to “subtitle” and its reuse identifier to “Tag Cell”:

cs193p - assignment #4 task #3
cs193p – assignment #4 task #3

The complete code is available on github.


Leave a Reply

Your email address will not be published.