cs193p – Assignment #5 Task #4

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

When the user chooses a place in a table view, you must query Flickr again to get an array of 50 photos from that place and display them in a list. The URL provided by FlickrFetcher’s URLforPhotosInPlace:maxResults: method will get this from Flickr.

Create a new class derived from the table-view-controller class to be used to show a list of photos with a public property to hold an array of photos:

@property (nonatomic, strong) NSArray *photos; // of Flickr photos NSDicitionary


Everytime the photos are set, reload the table:

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

The number of rows equals the number of photos:

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

The cells are populated with data from the photos for now (we will change that in the following task):

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Photo Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                            forIndexPath:indexPath];    
    NSDictionary *photo = self.photos[indexPath.row];
    cell.textLabel.text = [photo valueForKeyPath:FLICKR_PHOTO_TITLE];
    cell.detailTextLabel.text = [photo valueForKeyPath:FLICKR_PHOTO_DESCRIPTION];    
    return cell;
}

From this new class derive a new class with another public property to store the current place:

@property (nonatomic, strong) NSDictionary *place;

When the view did load or then the refresh action is triggered, download the available photos for the current place using another helper method:

#define MAX_PHOTO_RESULTS 50
- (IBAction)fetchPhotos
{
    [self.refreshControl beginRefreshing];
    [self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];    
    [FlickrHelper loadPhotosInPlace:self.place
                         maxResults:MAX_PHOTO_RESULTS
                       onCompletion:^(NSArray *photos, NSError *error) {
                           if (!error) {
                               self.photos = photos;
                               [self.refreshControl endRefreshing];
                           } else {
                               NSLog(@"Error loading Photos of %@: %@", self.place, error);
                           }
                       }];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self fetchPhotos];
}

The helper method is similar to the one used to load places:

+ (void)loadPhotosInPlace:(NSDictionary *)place
               maxResults:(NSUInteger)results
             onCompletion:(void (^)(NSArray *photos, NSError *error))completionHandler
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:[FlickrHelper URLforPhotosInPlace:[place valueForKeyPath:FLICKR_PLACE_ID] maxResults:results]
                                                completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
                                                    NSArray *photos;
                                                    if (!error) {
                                                        photos = [[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:location]
                                                                                                  options:0
                                                                                                    error:&error] valueForKeyPath:FLICKR_RESULTS_PHOTOS];
                                                    }
                                                    dispatch_async(dispatch_get_main_queue(), ^{
                                                        completionHandler(photos, error);
                                                    });
                                                }];
    [task resume];
}

The current place and the title of the view are set when selecting a cell in the places table:

- (void)preparePhotosTVC:(PlacePhotosTVC *)tvc
                forPlace:(NSDictionary *)place
{
    tvc.place = place;
    tvc.title = [FlickrHelper titleOfPlace:place];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    if ([segue.identifier isEqualToString:@"Show Place"] && indexPath) {
        [self preparePhotosTVC:segue.destinationViewController
                      forPlace:self.placesByCountry[self.countries[indexPath.section]][indexPath.row]];
    }
}

Finally add a new table view controllor in story board and link it to the just created class above. Don’t forget to set the cell identifier. Create a push segue from the cell of the first table view controller to this new controller. Don’t for set its identifier, too:

cs193p – assignment #5 task #4 - place photos table
cs193p – assignment #5 task #4 – place photos table

The complete code is available on github.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

3 thoughts on “cs193p – Assignment #5 Task #4”

  1. Trying to take course on my own and can’t get URL for PhotosInPlace to work. Very much a newbie.

    Flickr returns fail message of: “Method “flickr.photos.searcapih” not found”.

    Is query still working?

Leave a Reply

Your email address will not be published.