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

Article Photo by Nikita Vantorin

ios peek pop 3dtouch forceTouchCapability

Author

Dominik Ringler

iOS Developer

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

You may also like

Automate Debugging and Testing Workflows using ADB

While developing and testing we usually come across repetitive tasks involving manual efforts. Navigating to a certain part of the app, filling out sign up forms or simply taking screenshots are all time-consuming tasks. In this blog post we look at how we can utilize ADB (Android Debug Bridge) to...

Android
Is Flutter ready for production?

After hearing about Flutter from different sources and developers with all kinds of background we decided to try to rebuild an existing Android app in Flutter and see the the state of the Mobile framework.

iOS Android