An iOS framework that provides an interface for browsing and searching for photos from Unsplash.com.

Trying out DivingBoard

This repository includes an example app named "PhotoViewer" that uses the DivingBoard framework (watch a short demo video.):


In order to run it, you'll first need to sign up for an Unsplash app ID.

Once you have an Unsplash app ID, clone or download this repository. Then open DivingBoard/ExampleApp/PhotoViewer/PhotoViewer.xcodeproj in Xcode, and edit the file ViewController.swift to add the ID at the top where this appears:

(If you plan on contributing to DivingBoard, see "Contributing to DivingBoard" below for a better way to do this that will keep your Unsplash app ID out of commits.)

Then you'll be able to run PhotoViewer to see how DivingBoard works.

Installing via Carthage

  1. Install Carthage if you don't already have it.
  2. In the base directory of your project, create a file named "Cartfile" containing github "jim-rhoades/DivingBoard"
  3. Run carthage update in the terminal (in the same directory that you created the Cartfile). This will compile the framework and place it inside of your project folder at Carthage/Build/iOS/DivingBoard.framework.
  4. Open your project in Xcode, view your application target's "General" settings tab and scroll down to the "Embedded Binaries" section. Drag and drop the DivingBoard.framework file onto the "Embedded Binaries" section, and click "Finish" when prompted to.

DivingBoard Xcode setup 1

  1. On your application target's "Build Phases" tab, click the "+" button to add a new build phase and choose "New Run Script Phase".
  2. Add the following to the script area below the shell:
    /usr/local/bin/carthage copy-frameworks
  3. Under "Input Files" add:
  4. Under "Output Files" add:

DivingBoard Xcode setup 2

Installing via CocoaPods

  1. You can use CocoaPods to install DivingBoard by adding it to your Podfile:
platform :ios, '10.0'
pod 'DivingBoard', '~> 1.1.3'
  1. In the Terminal, navigate to the same directory that your Podfile is located, and run pod install.
  2. Remember to open your Xcode project using the .xcworkspace file instead of the original .xcodeproj file.

Launching DivingBoard in your app

To launch DivingBoard in your own app you'll need to get an instance of UnsplashPickerViewController and present it. The following code shows how you would do that to present it full screen:

let unsplashPicker = DivingBoard.unsplashPicker(withClientID: unsplashAppID,
                                                              presentingViewController: self,
                                                              modalPresentationStyle: .fullScreen)

present(unsplashPicker, animated: true, completion: nil)

In PhotoViewer's ViewController.swift you'll also find examples for presenting it as a popover and pushing it onto a UINavigationController stack.

Conforming to UnsplashPickerDelegate

The view controller that you're presenting DivingBoard from also needs to conform to the UnsplashPickerDelegate protocol, which consists of two methods:

func unsplashPickerDidCancel()
func unsplashPickerDidFinishPicking(photo: UnsplashPhoto)

See PhotoViewer's ViewController.swift file for examples.

Adhering to the Unsplash API guidelines

It is up to you to "play nicely" and adhere to the Unsplash API Guidelines.

DivingBoard includes a couple of methods that make adhering to the "technical guidelines" part easy:

  • Call DivingBoard.incrementUnsplashPhotoDownloadCount if you do something like save a photo to the camera roll. This method will call the Unsplash API's download_location endpoint to increment the download count for the photo on Unsplash.com. I highly recommend reading Unsplash API Guidelines: Triggering a Download for recommendations on when to do this. (PhotoViewer uses this when saving a photo to the camera roll.)

  • When linking to a photo or user on Unsplash.com, call DivingBoard.unsplashWebsiteURLWithReferral to get a URL with the proper attribution as described in Unsplash API Guidelines: Attribution. (PhotoViewer uses this when tapping on a photo or user avatar to view the photo/user on the Unsplash website.)

Helpful utilities

DivingBoard includes an extension on UIImageView to add the method loadImageAsync, which will load an image asynchronously and cache it to memory/disk.

Also included is the class LoadingView, which is a nice looking loading indicator.

You may want use either or both of these in your own app's implementation of unsplashPickerDidFinishPicking, for example:

func unsplashPickerDidFinishPicking(photo: UnsplashPhoto) {
    // show a loading indicator
    let loadingView = LoadingView()
    // load the photo
    let photoURL = photo.urls.full
    photoView.loadImageAsync(with: photoURL) { success in
        // remove the loading indicator

    dismiss(animated: true, completion: nil)

Contributing to DivingBoard

If you want to contribute to DivingBoard, I recommend that you create a file named "ClientID.swift" in the PhotoViewer Xcode project with the following content (replacing "YOUR_UNSPLASH_APP_ID" with your actual Unsplash app ID):

import Foundation

// Note that this file is in .gitignore and will NOT be added to the repository.
// (to prevent the app ID from leaking onto GitHub!)
let unsplashAppID = "YOUR_UNSPLASH_APP_ID"

Since "ClientID.swift" is included in .gitignore, that will enable you to run and test changes to DivingBoard and PhotoViewer without risk of accidentally including your Unsplash app ID in a commit.


  • [ ] change from a square grid layout to a waterfall layout that shows uncropped photos instead of square crops:
  • [ ] improve the unit tests - in particular, there should be tests for UnsplashClient's requestPhotosFor method using a stub / fake data (the project includes files containing real JSON data from the Unsplash APIā€¦ test_data_photos.json and test_data_search.json, but they aren't currently being used)