Assignment #5 Task #1

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

The fifth assignment continues the application from the last assignment which create a navigation-based application to let users browse photos by looking in the most popular Flickr locations, then click on any they are interested in to see a photo of it. This assignment will fix problems with the responsiveness of the user-interface by using GCD to move blocking activity out of the main thread and by cacheing the image data received from Flickr. In addition, some maps will be added and the application will become Universal.

Your application must implement all the required tasks from the last assignment (and all the required tasks in this assignment) without doing any Flickr fetching or file system interactions in the main thread. Your user-interface should be responsive to the user at all times (i.e. the main thread should never be blocked).


Starting with the download of the top places we move that part of the code from viewDidLoad to viewWillAppear. This way the table will get refreshed every time the user returns to this screen. Then we create a new queue in which the actual download will happen, but do not write the new places to our model because this would try to update the table view from inside our asynchronous queue. Instead we call the main queue and set the model there:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    dispatch_queue_t queue = dispatch_queue_create("Flickr Downloader", NULL);
    dispatch_async(queue, ^{
        NSArray *places = [FlickrFetcher topPlaces];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.places = places;
        });
    });
    dispatch_release(queue);
}

Same procedure for the top-photos-table-view-controller class:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.navigationItem.title = [FlickrData titleOfPlace:self.place];    
    dispatch_queue_t queue = dispatch_queue_create("Flickr Downloader", NULL);
    dispatch_async(queue, ^{
        NSArray *photos = [FlickrFetcher photosInPlace:self.place maxResults:NUMBER_OF_PHOTOS];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.photos = photos;
        });
    });
    dispatch_release(queue);
}

Loading the photos works similar. But before we return to the main queue we check if the view is still on screen, otherwise we skip the expensive drawing.

    dispatch_queue_t queue = dispatch_queue_create("Flickr Downloader", NULL);
    dispatch_async(queue, ^{
        NSURL *url = [FlickrFetcher urlForPhoto:self.photo format:FlickrPhotoFormatLarge];
        NSData *data = [NSData dataWithContentsOfURL:url];
        if (self.imageView.window) dispatch_async(dispatch_get_main_queue(), ^{
            UIImage *image = [UIImage imageWithData:data];        
            // setting the size, scrollview, .... 
            [self.imageView setNeedsDisplay];
        });
    });
    dispatch_release(queue);

The complete code for this task is available at github.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.