Color Mode


    Language

Adding Peek and Pop to your View Controllers

November 27, 2017

With iOS 9, new iPhone models add a third dimension to the user interface, called force touch, or more commonly 3D Touch.

A user can now press your Home screen icon to immediately access functionality provided by your app. Within your app, a user can now press certain views to see previews of additional content and gain accelerated access to features.

Peek and Pop

iOS 9 lets you configure view controllers to allow the use of peek, which provides a preview of additional content when a user presses on a specified view, and pop, which commits to viewing that content and navigates to it.

This interaction proceeds through three phases.

  1. Indication that content preview is available
  2. Display of the preview, known as a peek, with options to act on it directly, known as peek quick actions
  3. Optional navigation to the view shown in the preview, known as a pop

Setup

Lets imagine that we have 2 UIViewControllers in our app. One has a UICollectionView as its main UI, for example to show a list of images, we shall call it ImageViewController. The other one is a DetailViewController that will be presented if one of the images is pressed. This should be a very common scenario in most apps.

If we want to use Peek and Pop we first have to check wether 3D touch is supported and if it is, register the previewing delegate.

class ImageViewController: UIViewController {

  override func viewDidLoad() {
      super.viewDidLoad()

      // Do your usual setup
      ...

      // Register peek and pop if available
      guard traitCollection.forceTouchCapability == .available else { return }
      registerForPreviewing(with: self, sourceView: view)
    }
}

Implement The Delegate

Next we need to implement the above registered delegate, called UIViewControllerPreviewingDelegate. This delegate has 2 methods, 1 for peeking and 1 for popping.

class ImageViewController: UIViewController {
    ...
}

// MARK: - UI View Controller Previewing Delegate

extension ImageViewController: UIViewControllerPreviewingDelegate {

    /// Peek
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {

      // Get the index path of the cell we are force touching on
      guard let indexPath = collectionView.indexPathForItem(at: location) else { return nil }

      // Get the actual cell instance for the index path
      guard let cell = collectionView.cellForItem(at: indexPath) else { return nil }

      // Instantiate the detail view controller
      guard let detailVC = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController else { return nil }

      // Update the detail view controllers data source
      let image = images[indexPath.row]
      detailVC.image = image

      // Set the content size for the detail view controller
      detailVC.preferredContentSize = CGSize(width: 0, height: 300)

      // Set the source rect of the previewing context
      previewingContext.sourceRect = cell.frame

      // Return the view controller for peeking
      return detailVC
    }

    /// Pop
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        showViewController(viewControllerToCommit, sender: self)
    }
}

For peeking, the logic is almost similar to using Segues. We need to get a reference to the cell we are touching and instantiate the DetailViewController and update its data source. We also need to set a preferred content size of the DetailViewController and finally we need to set the sourceRect of the previewing context to the frame of the cell we are touching.

Popping on the other hand is very straightforward, simply show the view controller that your are peeking at.

Previewing Actions

If you now run your app and force touch on an image you should be able to get a preview of the DetailViewController.

At this stage we can also add some custom button actions to this view, for example a like or delete action. This allows a user to do some action in the DetailViewController while peeking without actually navigating to it.

Implementing these actions is also very easy. Go to your DetailViewController and add your actions, its quite similar to using a UIAlertController.

class DetailViewController: UIViewController {
    ...
}

// MARK: - UI Preview Action Items

extension DetailViewController {

      override var previewActionItems: [UIPreviewActionItem] {

          let likeAction = UIPreviewAction(title: "Like", style: .default) { (action, viewController) in
              // add some like logic
            }

          let deleteAction = UIPreviewAction(title: "Delete", style: .destructive) { (action, viewController) in
              // add some delete logic
          }

          return [likeAction, deleteAction]
      }
}

Conclusion

That is all there is to peek and pop. It is a very powerful feature that should dramatically improve the flow of an app that implements it. It allows you to use the app in such a way where you can get glances and previews of screens without having to navigate to those screens. This should make any app more productive and efficient and therefore is a feature that should be supported by all app makers.

Resources

  • https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/Adopting3DTouchOniPhone/3DTouchAPIs.html#//apple_ref/doc/uid/TP40016543-CH4-SW1
  • https://the-nerd.be/2015/10/06/3d-touch-peek-and-pop-tutorial/

Article Photo by Nikita Vantorin

iospeekpop3d touchforce touch capability

Author

Dominik Ringler

Dominik Ringler

iOS Developer

iOS games and apps developer. I love Swift very much. /ˈɡɪf/

You may also like

November 7, 2024

Introducing Shorebird, code push service for Flutter apps

Update Flutter apps without store review What is Shorebird? Shorebird is a service that allows Flutter apps to be updated directly at runtime. Removing the need to build and submit a new app version to Apple Store Connect or Play Console for review for ev...

Christofer Henriksson

Christofer Henriksson

Flutter

May 27, 2024

Introducing UCL Max AltPlay, a turn-by-turn real-time Football simulation

At this year's MonstarHacks, our goal was to elevate the sports experience to the next level with cutting-edge AI and machine learning technologies. With that in mind, we designed a unique solution for football fans that will open up new dimensions for wa...

Rayhan NabiRokon UddinArman Morshed

Rayhan Nabi, Rokon Uddin, Arman Morshed

MonstarHacks

ServicesCasesAbout Us
CareersThought LeadershipContact
© 2022 Monstarlab
Information Security PolicyPrivacy PolicyTerms of Service