A photo gallery for iOS with a modern feature set. Similar features as the Facebook photo browser.

Related tags

Image EBPhotoPages


”A photo gallery can become a pretty complex component of an app very quickly. The EBPhotoPages project demonstrates how a developer could use the State Pattern to control the behavior of an interface with numerous features. This pattern grants the ability to create new behaviors for a custom implementation of the EBPhotoPages photo gallery without having to modify or understand much of the original source code. The goal was to design a photo gallery class that would smoothly support whatever use cases would be required in the future.”

Alt text|Alt text Alt text Alt text|Alt text Alt text|Alt text Alt text

What is this?

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.

The library was designed using a state pattern to control the behavior of the gallery, so that other developers can easily modify or add new states without having to understand too much of the original code.

Quick Feature list:

  • Photo Tagging: Create/Edit/Delete
  • Photo Commenting: Create/Edit/Delete
  • Photo Sharing:
  • Photo Reporting:
  • Speficy User Permissions per Photo for commenting, tagging, deletion, reporting, etc.
  • Page Based Scrolling
  • Photos give immediate bounce feedback when single tapped, for a juicy interface feel.
  • Toggle Tags On/Off
  • Pinch, Zoom, Pan Photos with gestures.
  • Scrollable captions, variable lengths with auto-dimming background
  • Show/Hide UI elements with a single tap gesture
  • Asynchronous loading of data (through NSOperationQueue)
  • Activity Indicator per Photo.
  • Content Mode AspectFit/Center auto detection (prevent photos smaller than the screen from blowing up)
  • Full landscape/portrait orientation support
  • Resolution independent support (iPad/iPhone)
  • Touch and hold comments to copy or delete
  • Flat UI Design
  • Comments icon shows the number of comments posted (if there are any)
  • Other stuff

How do I use it?

  1. Add the QuartzCore.framework, CoreGraphics.framework and AVFoundation.framework to your project.

  2. Add the EBPhotoPagesController folder from this repo to your app.

  3. Implement the EBPhotoPagesDataSource(required) and EBPhotoPagesDelegate(optional) protocols in an object(s) you plan to use as the datasource and delegate for your EBPhotoPagesController instance.

  4. Then, initialize and present the photoPagesController:

EBPhotoPagesController *photoPagesController = [[EBPhotoPagesController alloc] 
                                               initWithDataSource:aDataSource delegate:aDelegate];

[self presentViewController:photoPagesController animated:YES completion:nil];

How do I customize this?

The EBPhotoPagesFactory class is meant to be the one-stop shop for all UI objects. This class is responsible for instantiaing UI Elements and returning them to the EBPhotoPagesController. If you wish to customize the look of your photo gallery implementation, this is the first place you should check for whatever you want to customize. Some other UI elements are not yet created by this class, but the plan is to eventually move them into it.

By subclassing this class and overriding relevant methods, you can control how the UI objects will look before they get sent back to the EBPhotoPagesController to be used.

If you are going to create a custom EBPhotoPagesFactory subclass, you will have to init your EBPhotoPagesController with one of the init methods that lets you pass an EBPhotoPagesFactory instance, such as this one:

- (id)initWithDataSource:(id<EBPhotoPagesDataSource>)dataSource 
       photoPagesFactory:(EBPhotoPagesFactory *)factory 

How do State Objects work in EBPhotoPages?

At any given time, the photo gallery has a state object assigned as its current state, when a user event is received, the photo gallery’s state object takes responsibility for how the photo gallery should respond.

By convention, state objects are decoupled from each other. This means they are completely unaware of other state objects, and they also hold no data of their own. You can freely create and destroy them without fear (or guilt…).

When a state object decides it’s time to transition to a new state, it simply calls upon a method within the photo gallery that replaces the current state object with a new instance of the next state object.

To create a new custom State for your implementation of the photo gallery, you should do two things:

  1. Create a new state object that is a subclass of the EBPhotoPagesState object, and override the methods you’re interested in. (example: EBPhotoPagesCoolNewState)

  2. Create a category of the EBPhotoPages that contains the method(s) for your custom transitions. The purpose of a transition method is usually to set the “currentState” object of the EBPhotoPagesController to a new instance of your new custom state. (example: -(void)transitionToCoolNewState;)

  3. Decide how the user will reach this new custom state. If there is a special button in the interface that takes the user to this state when tapped, then make sure the EBPhotoPages calls your new transition method for that user event. If you are injecting this custom state somewhere in between the default state machine flow (the normal default behavior of the EBPhotoPagesController), then this may require a bit more overriding of existing classes so that your new state is reached instead of the original ones.

  4. Don’t forget to implement some way for a user to exit your custom state and go back to a default idle browsing state!

Tell me more about the features.

  • Tags: If you don’t already know, a tag is a point of interest at a certain spot within a photo (usually a person’s face). A tag’s coordinates in a photo are normalized between 0 and 1, so that the point is independent of the actual photo’s current resolution. For usability purposes, tags do not sit exactly on the pixel that was tagged, but rather they have padding that positions them a few pixels below it so the point of interest isn’t overly obscured by the tag.

  • Comments: As you can imagine, a comment is a user submitted text that accompanies a photo. The comment also includes meta data such as the user’s name, their avatar, and time of posting. The order of the comments appearance is determined by the order in which the datasource returns them.

  • Zero Graphic Files: Amazingly, the EBPhotoPages library requires no graphic files for its default toolbar icons because everything is drawn natively in code and converted to a UIImage. However, if you want to use actual graphic files for custom icons, you can always provide them directly by returning them through the appropriate methods as well.

  • Sharing: The EBPhotoPages provide a default activity sheet for sharing a photo. You can customize what kind of sheet and services are displayed by returning a custom one from your datasource object.

  • Reporting Photos: When a user comes across inappropriate content there needs to be a way to let them report it. The EBPhotoPages provides a report option that informs your datasource that a photo has to be marked as inappropriate.

What are some things to consider when implementing EBPhotoPages?

  • Caching: The EBPhotoPages do not implement their own caching system for photo content. That responsibility is passed on to whatever you decide to use as the datasource for the EBPhotoPages. You should probably pre-fetch content ahead of time and save it for faster loading if speed is a concern (which is usually the case…).

  • User Permission: When a user takes some action on a photo such as commenting or tagging or deleting (and others), the EBPhotoPages will ask its delegate if the user has permission to do that. This approach creates flexibility in controlling what a user can and can’t do on a per-photo basis. This means you should think about how to organize user permissions on your end.

  • Creating/Destroying content: Prepare your backend for the ability to post new content or delete existing content when the EBPhotoPages notifies your delegate that the user has initiated such an action. It would not be a good idea to let the EBPhotoPages itself be responsible for actual removing or posting the data to your servers directly.

How can I help?

Although this library has a lot of features and over 5,000 lines of code, there’s still some challenges to solve. Feel free to improve on the library and submit pull requests. In particular, these areas need some attention:

  • More Caption Content: The caption block might be a good place to show the number of likes a photo has, along with the author, date of posting, location and whether the photo is private or public. Bonus if these things are tappable.

  • Page Indicator: A page indicator that shows how many photos there are and which photo you are currently on (perhaps in the top left corner) would be useful.

  • TagPopovers: Bless the tag popovers, they do their best to stay within the photo boundaries so they are not cut off screen, but this behavior could still be improved. Right now, the implementation is a bit simplistic, the arrow points need to be drawn closer to where the actual tagged pixel is, not just shoved along. Consideration of a photo’s zoom scale should also be taken into account.

  • Deleting stuff: Once upon a time deleting photos worked flawlessly, but somewhere along the way there was an update and something broke and now it’s kind of buggy (though photos do delete from the datasource). The main problem is that the UIPageViewController doesn't discard the old view controller of the deleted photo until you scroll it out of existence.

  • Alternative toolbar layouts: The current toolbars work fine, but there’s always better or different ways of doing things. If a developer could simply set a toolbar to adopt a different layout style by just setting an enumerated property to a new value that would be sweet. The more variety the better.

  • iOS 7 features: This project was started a bit before iOS 7. Having the option to include some of the physics based features or parallax into the gallery would be awesome. Remember to add a property to toggle these on and off.

  • Networking: The code related to loading content is made to run asynchronously, but it has not been thoroughly tested on a consumer web scale application of any sort. Someone with more experience here may want to try offering some improvements from practical experience.

  • Likes: One of the more noticeable features missing from EBPhotoPages is the ability to “like” photos.

  • Localization: Every string used for the interface is ready for localization with NSLocalizedString. Currently, there are no localization files provided with the library so only English is represented. If you want your language for your culture represented, you should consider adding and sharing localization files to the project!

  • Comment Pagination: When a photo amasses an staggering number of comments, it would be impractical to make a web request for all of them at once. A system for allowing pagination of comments is needed, as currently the EBPhotoPages does not allow for new comments to be loaded in by user request. Another alternative is to implement an infinite scroll, by informing the datasource what cell a user has scrolled to in the comments so that it may download more comments as needed.

  • Presentation Transitions: Originally the EBPhotoPages was intendend to expand from a thumbnail into a full gallery, then shrink back to an image thumbnail when the user exited the gallery. This was never implemented, however, there are other variations of transitions that would be interesting to see as well.

Any issues or bugs?

  • The loading indicator has a tendency to not show up sometimes.
  • Deleting comments doesn’t animate too smoothly.
  • (!)Deleting a photo doesn't remove it immediately from the gallery, scrolling backward shows old data. (However, the photo is still deleted from the data model)
  • (!)Deleting a photo at the end of the gallery is causing a crash perhaps due to scrolling beyond index?
  • Creating tags while in landscape mode is a bit messed up.
  • Editing a tag doesn't work at the moment.
  • Toolbar icons disappear after deleting a tag, have to tap photo twice to return them.
  • When long pressing a comment to view Copy and Delete options, only the relevant comment should stay highlighted.
  • Long pressing a photo then selecting the Tag Photo option should start a new tag at the location of the longpress, instead of just entering the tagging mode.

Got a License?

EBPhotoPages uses the MIT License:

Copyright (c) 2014 Eddy Borja

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


Who made this?

EBPhotoPages and its components were created by Eddy Borja.

iPhone PSD Template by Mikael Eidenberg.

These days I'm unable to continue working on this project due to other obligations, but I'm always open to pull requests.

Contributors can always be found here.

What else?

Be sure to check out these other libraries:


  • can default select photo when i use in the more photos ?

    can default select photo when i use in the more photos ?

    Hi, Eddy sorry, my english isn't good. i use this EBPhotoPages to my app, have an one questions, when i bind 3 photos in the one TableViewCell, i click it, but always begin EBPhotoPages at photo 1, how to set default photo index when i click photo 2... T.T

    thank you. Eric

    opened by ilyi1116 4
  • Toolbars alpha configurable in factory

    Toolbars alpha configurable in factory

    I've noticed that you can't really change the alpha for toolbars - there is one off method but every time you click on activity or share button the alpha gets restored back to 1.0 value ignoring whatever was the last alpha set. I've added methods to factory which can override the default alpha for toolbars.

    opened by 3ph 3
  • Few commits

    Few commits

    Hey Eddy, love the project. I went ahead and updated the .gitignore file, removed the sizewithfont stuff, and added an animation when deleting a tag.

    I actually left a few animations in there for the tag deletion, right now it just makes scale to 0,0, but the other options are reduce its alpha, move it off screen, and I'm sure theres plenty more depending on what you want to do.

    I tried looking at the deletion issue, its very weird to me, I'm not sure why that happens but id like to look at it more in the future.

    opened by thefotes 3
  • Update UIActionViewController popover for iOS8 on iPad.

    Update UIActionViewController popover for iOS8 on iPad.

    The "share" UIActionViewController was crashing on iOS8 on the iPad due to new requirements that a "popoverPresentationController" item be set for the UIActionViewController to display "from". This update uses the share button as that frame of reference.

    opened by adamgall 1
  • Comments lower toolbar button not hidden when comments disabled

    Comments lower toolbar button not hidden when comments disabled

    There's a bug on this line,


    Should be lowerItems not upper.

    opened by JoeMatt 1
  • `UIActionSheet` has been deprecated.

    `UIActionSheet` has been deprecated.

    The action sheets currently being used in EBPhotoPagesFactory were deprecated in iOS 8.3. Could you update to use UIAlertController with style ActionSheet?

    opened by JettF 0
  • Enable customizing the user interface of the image viewer

    Enable customizing the user interface of the image viewer

    I created a global class called EBConfig that allows developers to change different features of the user interface easily e.g font, font color, date formatting etc.

    I also added a feature to load the comment avatars from aNSURL opposed to a UIImage incase there is networking involved. Feel free to change anything, I just had to change a few things to work for my project.

    opened by jesster2k10 0
  • Is this repo still being mantained?

    Is this repo still being mantained?

    Hey @EddyBorja, are you still maintaining this control? I would like to use it, but I see lot's of things you use here were deprecated and that's kind of a show stopper to me... Any idea if you'll be able to keep working in this? If not I think it might be a good idea to find someone to transfer the project to :)

    opened by mradzinski 6
  • Possible problem with Apple's Private APIs

    Possible problem with Apple's Private APIs

    My app just got rejected with this message:

    Your app uses or references the following non-public APIs:


    Searching my project for this string showed only the classes in your library. This is obviously a false positive from Apple since I used this library for the last couple of months and updated my app with no problems what so ever. You might want to rename the "commentText" method in EBPhotoCommentProtocol and the selectors that reference this method

    opened by potecuta 0
  • cannot hide commentsBarButtonItem

    cannot hide commentsBarButtonItem

    Haven't remove commentsBarButtonItem from mutableLowerItems while checking commentsAreViewable. Please refer to the last line at source code below from EBPhotoPagesController.m

    solution: change [mutableUpperItems removeObject:self.commentsBarButtonItem]; to [mutableLowerItems removeObject:self.commentsBarButtonItem];

    • (void)updateToolbarsWithPhotoAtIndex:(NSInteger)index { NSArray *upperItems = [self.photoPagesFactory upperToolbarItemsForPhotoPagesController:self inState:self.currentState];

      NSArray *lowerItems = [self.photoPagesFactory lowerToolbarItemsForPhotoPagesController:self inState:self.currentState];

      NSMutableArray *mutableUpperItems = [NSMutableArray arrayWithArray:upperItems]; NSMutableArray *mutableLowerItems = [NSMutableArray arrayWithArray:lowerItems];

      BOOL taggingAllowed = [self.photosDataSource respondsToSelector:@selector(photoPagesController:shouldAllowTaggingForPhotoAtIndex:)] ? [self.photosDataSource photoPagesController:self shouldAllowTaggingForPhotoAtIndex:index] : YES;

      BOOL activitiesAllowed = [self.photosDataSource respondsToSelector:@selector(photoPagesController:shouldAllowActivitiesForPhotoAtIndex:)] ? [self.photosDataSource photoPagesController:self shouldAllowActivitiesForPhotoAtIndex:index] : YES;

      BOOL commentsAreViewable = [self.photosDataSource respondsToSelector:@selector(photoPagesController:shouldShowCommentsForPhotoAtIndex:)] ? [self.photosDataSource photoPagesController:self shouldShowCommentsForPhotoAtIndex:index] : YES;

      if([self.photosDataSource photoPagesController:self shouldExpectPhotoAtIndex:index] == NO){ taggingAllowed = NO; activitiesAllowed = NO; commentsAreViewable = NO; }

      if(taggingAllowed == NO){ [mutableUpperItems removeObject:self.tagBarButtonItem]; [mutableLowerItems removeObject:self.tagBarButtonItem]; }

      if(activitiesAllowed == NO){ [mutableUpperItems removeObject:self.activityBarButtonItem]; [mutableLowerItems removeObject:self.activityBarButtonItem]; }

      if(commentsAreViewable == NO){ [mutableUpperItems removeObject:self.commentsBarButtonItem]; [mutableUpperItems removeObject:self.commentsBarButtonItem]; }

    opened by flysec 0
  • 0.9.1(Apr 11, 2014)

    SizeWithFont has been replaced, tag deletions animate, "Commenting is Disabled." placeholder text added when commenting isn't allowed, and some other minor stuff.

    Source code(tar.gz)
    Source code(zip)
Eddy Borja
The sky above the port was the color of television, tuned to a dead channel.
Eddy Borja
Jogendra 113 Nov 28, 2022
Photo Browser / Viewer inspired by Facebook's and Tweetbot's with ARC support, swipe-to-dismiss, image progress and more

IDMPhotoBrowser IDMPhotoBrowser is a new implementation based on MWPhotoBrowser. We've added both user experience and technical features inspired by F

Thiago Peres 2.7k Dec 21, 2022
Image gallery similar to Adidias' app, built in SwiftUI

TripleStackGallery TripleStackGallery is a image gallery component, which displays a set of images as a stack of three images, always displaying the i

Tomás Martins 5 Aug 29, 2022
An iOS/tvOS photo gallery viewer, useful for viewing a large (or small!) number of photos.

This project is unmaintained. Alex passed away in an accident in late 2019. His love of iOS development will always be remembered. AXPhotoViewer AXPho

Alex Hill 596 Dec 30, 2022
This simple cordova plugin will download picture from an URL and save to IOS Photo Gallery.

Photo Viewer This plugin is intended to download a picture from an URL into IOS Photo library.. How to Install Cordova: cordova plugin add https://git

Alwin jose 1 Oct 23, 2021
iOS photo gallery written in Swift

SwiftPhotoGallery Overview A full screen photo gallery for iOS and tvOS written in Swift. Photos can be panned and zoomed (iOS only) Pinch to zoom (iO

Justin Vallely 271 Dec 17, 2022
Nilay Dagdemir 0 Jan 23, 2022
Photo Gallery App demo using a REST API

Photo Gallery iOS App - (Using Rest API) A demo Photo Gallery App using a Rest API using MVVM architecture in Swift + UIKit. Overview Fully Programmat

Neel Mewada 2 Nov 22, 2021
FacebookImagePicker is Facebook album photo picker written in Swift.

Features • Installation • Usage • Translation • License GBHFacebookImagePicker is Facebook's album photo picker written in Swift, built to provide a s

Florian Gabach 231 Dec 17, 2022
Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift

SKPhotoBrowser [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) Simple PhotoBrowser

keishi suzuki 2.4k Jan 6, 2023
A simple iOS photo and video browser with grid view, captions and selections.

MWPhotoBrowser A simple iOS photo and video browser with optional grid view, captions and selections. MWPhotoBrowser can display one or more images or

Michael Waterfall 8.8k Dec 27, 2022
A modern photo viewing experience for iOS.

NYTPhotoViewer NYTPhotoViewer is a slideshow and image viewer that includes double-tap to zoom, captions, support for multiple images, interactive fli

The New York Times 2.8k Jan 5, 2023
IRGallery-swift is a powerful gallery for iOS.

IRGallery-swift IRGallery-swift is a powerful gallery for iOS. Features Captions. Rotation support. Load images locally or from a web URL. Custom UITa

Phil Chang 1 Oct 6, 2021
FMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor

FMPhotoPicker is a modern, simple and zero-dependency photo picker with an elegant and customizable image editor Quick demo Batch select/deselect Smoo

Cong Nguyen 648 Dec 27, 2022
🖼 Gallery App for Actomaton (async/await + Elm Architecture) + SwiftUI.

?? Actomaton-Gallery Gallery App for Actomaton (async/await + Elm Architecture) + SwiftUI. NOTE: Most of the code are reused from Harvest-SwiftUI-Gall

Yasuhiro Inami 44 Dec 20, 2022
Applies filter to a selected image from the Gallery using Combine

CombinePhotoFiltering App CombinePhotoFiltering is an app that applies sepia and bloom to a selected picture from the Photos app. Highlights The app i

Mauricio Esteves 0 Nov 14, 2021
Gallery has a clearer flow based on albums and focuses on the use case of selecting video

Description We all love image pickers, don't we? You may already know of ImagePicker, the all in one solution for capturing pictures and selecting ima

null 1 Sep 14, 2022
React-native-photo-editor - Photo editor using native modules for iOS and Android

?? Image editor using native modules for iOS and Android. Inherit from 2 available libraries, ZLImageEditor (iOS) and PhotoEditor (Android)

Baron Ha. 244 Jan 5, 2023
DGCropImage - A photo cropping tool which mimics Photo.app written by Swift

DGCropImage A photo cropping tool which mimics Photo.app written by Swift. This

donggyu 11 Jul 14, 2022