cs193p – Assignment #4 Task #5

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

When the user then chooses a particular photo from the list, display it inside a UIScrollView that allows the user to pan and zoom.

Like in the previous task, you can safe some time be reusing code from Shutterbug.

In storyboard drag out a new view controller. Create a new subclass for it and link them. Add a scroll view and provide an outlet for it in the new class:

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

Create a push segue from the cell of the second table to the new view controller and set its identifier to “Show Image”:

cs193p - assignment #4 task #5
cs193p – assignment #4 task #5

Create a public property to hold the URL of the image:

@property (nonatomic, strong) NSURL *imageURL;

… and a private property to actually hold the image view and initialize it lazily:

@property (strong, nonatomic) UIImageView *imageView;
- (UIImageView *)imageView
    if (!_imageView) {
        _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
    return _imageView;

When ever somebody changes this URL, reset the image.

- (void)setImageURL:(NSURL *)imageURL
    _imageURL = imageURL;
    [self resetImage];

Finally the controller needs to be declared as delegate for the scroll view:

@interface ImageViewController () <UIScrollViewDelegate>
- (void)viewDidLoad
    [super viewDidLoad];
	[self.scrollView addSubview:self.imageView];
    self.scrollView.minimumZoomScale = 0.2;
    self.scrollView.maximumZoomScale = 5.0;
    self.scrollView.delegate = self;
    [self resetImage];

… and the table view controller needs to set the correct photo:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    if ([sender isKindOfClass:[UITableViewCell class]]) {
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
        if (indexPath) {
            if ([segue.identifier isEqualToString:@"Show Image"]) {
                if ([segue.destinationViewController respondsToSelector:@selector(setImageURL:)]) {
                    NSURL *url = [FlickrFetcher urlForPhoto:self.photos[indexPath.row] 
                    [segue.destinationViewController performSelector:@selector(setImageURL:) 
                    [segue.destinationViewController setTitle:[self titleForRow:indexPath.row]];

Before you do so, check if there is a scroll view – which there is not when the view is not on screen yet, e.g. when preparing a segue … Resetting means removing an old image and its settings in the scroll view, loading it and setting the new properties:

- (void)resetImage
    if (self.scrollView) {
        self.scrollView.contentSize = CGSizeZero;
        self.imageView.image = nil;        
        NSData *imageData = [[NSData alloc] initWithContentsOfURL:self.imageURL];
        UIImage *image = [[UIImage alloc] initWithData:imageData];
        if (image) {
            self.scrollView.zoomScale = 1.0;
            self.scrollView.contentSize = image.size;
            self.imageView.image = image;
            self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);

The complete code is available on github.


One thought on “cs193p – Assignment #4 Task #5”

  1. Thanks for sharing! Just a note… As stated in lecture 9, I guess a delegate method to specify view to zoom is missing. I added the code below and the zoom worked fine:

    – (UIView *)viewForZoomingInScrollView:(UIScrollView *)sender
    return self.imageView;

    Thanks again!

Leave a Reply

Your email address will not be published.