EBPhotoPages is a photo gallery library for displaying pages of photos and their meta data in a scrollview. Users are able to zoom photos in and out, as well as create, edit or delete comments and tags, share or delete a photo, and report inappropriate photos. All photos and content are loaded asynchronously. User permissions for a photo are controlled through a delegate protocol. No graphic files are required for the gallery as icons are drawn in code.

In the previous post, I talked about how to display GIF images pulled from parse in an iOS app. Let’s take that a step further and include the GIF images in EBPhotoPages.

Install required pods

Start by adding the following to your Podfile

pod 'EBPhotoPages', '~> 0.9'
pod 'FLAnimatedImage', '~> 1.0'

Customize EBPhotoView

If you dive into the code, you will notice that the first thing we need to do is to customize the EBPhotoView to use an animated image view instead of a normal image view.

@interface EBPhotoView ()
@property(strong, readwrite) UIImageView *imageView;

- (void)initialize;
- (void)loadTouchGestureRecognizers;
- (void)beginObservations;
- (void)setContentModeForImageSize:(CGSize)size;
- (void)stopObservations;
- (void)repositionTags;

@implementation QBAnimatedPhotoView
- (void)initialize {
    [self setDelegate:self];
    [self setShowsVerticalScrollIndicator:NO];
    [self setShowsHorizontalScrollIndicator:NO];
    [self setBouncesZoom:YES];
    [self setDecelerationRate:UIScrollViewDecelerationRateFast];

    [self setAlpha:0];
    [self setImageView:[[FLAnimatedImageView alloc] initWithFrame:self.bounds]];
    [self addSubview:self.imageView];
    [self.imageView setContentMode:UIViewContentModeScaleAspectFit];
    [self setClipsToBounds:NO];
    [self.imageView setClipsToBounds:NO];
    [self setMaximumZoomScale:5.0];
    [self setShowsHorizontalScrollIndicator:NO];
    [self setShowsVerticalScrollIndicator:NO];

    [self setBackgroundColor:[UIColor clearColor]];
    [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    [self setAdjustsContentModeForImageSize:YES];
    [self loadTouchGestureRecognizers];
    [self beginObservations];

- (void)setImage:(UIImage *)image {
    NSAssert(image, @"Image cannot be nil");
    [self.imageView setAlpha:0];
    [UIView animateWithDuration:0.1
                         [self.imageView setAlpha:1];
                     } completion:nil];

    [self setContentModeForImageSize:image.size];
    if ([image isKindOfClass:[FLAnimatedImage class]]) {
        [self.imageView setAnimatedImage:image];
    } else {
        [self.imageView setImage:image];

#pragma mark - Key Value Observing

- (void)beginObservations {
    [super beginObservations];
    [self.imageView addObserver:self forKeyPath:@"animatedImage" options:NSKeyValueObservingOptionNew context:nil];

- (void)stopObservations {
    [super stopObservations];
    [self.imageView removeObserver:self forKeyPath:@"animatedImage"];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    if (object == self.imageView && [keyPath isEqualToString:@"animatedImage"]) {
        [self repositionTags];
        if (self.imageView.animatedImage) {
            [self setAlpha:1];
        } else {
            [self setAlpha:0];

Customize EBPhotoViewController

The next class that we need to subclass is the EBPhotoViewController to use our photo view instead of the default EBPhotoView

@interface EBPhotoViewController ()
@property(weak, readwrite) EBPhotoView *photoView;
@property(strong) NSMutableSet *activeOperations;

- (void)initialize;
- (void)loadCommentsView;
- (void)beginObservations;

@implementation QBPhotoViewController 
- (void)initialize {
    [self setActiveOperations:[NSMutableSet set]];

    CGRect viewFrame = [[UIScreen mainScreen] bounds];
    UIView *mainView = [[UIView alloc] initWithFrame:viewFrame];
    [self setView:mainView];

    EBPhotoView *newPhotoScrollView = [[QBAnimatedPhotoView alloc] initWithFrame:viewFrame];
    [self setPhotoView:newPhotoScrollView];
    [mainView addSubview:newPhotoScrollView];

    [self loadCommentsView];

    [self beginObservations];

Use our Photo View Controller

The last step is to use our newly created QBPhotoViewController by implementing the photoViewControllerWithIndex:forPhotoPagesController: method in our EBPhotoPagesFactory subclass. Just add the following in your EBPhotoPagesFactory subclass.

- (EBPhotoViewController *)photoViewControllerWithIndex:(NSInteger)index forPhotoPagesController:(EBPhotoPagesController *)controller {
    return [[QBPhotoViewController alloc] initWithIndex:index delegate:controller];

Phew! That was some work. If you ever need help setting this up or have some questions, don’t hesitate to write to me at diwakar.sapan@gmail.com or leave a comment.