In this tutorial, we’ll be discussing and implementing the 3D Touch functionality in our iOS Application.
Peek and Pop
Peek and Pop is a functionality that is available in iPhone 6s and above. It occurs when a user presses deeply onto the screen.
we can show a preview of the next screen in a small window along with Quick Actions too.
It gives the feeling of a 3D touch.
Instead of going onto the next screen, you can quickly preview the content using 3D Touch.
Pressing Hard shows you the preview.
Pressing Harder would show the entire screen.
To do it automatically using Storyboard, we can always select the option “Preview & Commit Segues” in the attributes inspector on the segue.
In order to use Peek and Pop feature, UIViewControllerPreviewingDelegate protocol must be added to the ViewController class and the delegate methods need to be implemented.
previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint)
previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
Learn by example!
In the next section, we’ll learn by implementing Peek and Pop on a UITableView in our iOS Application.
First the storyboard!
Project Storyboard
Let’s embed the First View Controller in a NavigationController.
Connect the IBOutlet for all the elements to their respective View Controller.
Code
In order to implement Peek and Pop, we need to first register the view on which the 3D interaction is enabled.
We can add the following statement in the viewDidLoad method for that:
1 2 3 4 5 |
if( traitCollection.forceTouchCapability == .available){ registerForPreviewing(with: self, sourceView: myTableView) } |
The code for the ViewController.swift file is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate { @IBOutlet weak var myTableView: UITableView! var myArray = ["apple","windows","amazon"] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. if( traitCollection.forceTouchCapability == .available){ registerForPreviewing(with: self, sourceView: myTableView) } myTableView.delegate = self myTableView.dataSource = self } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = myArray[indexPath.row] return cell } func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { guard let indexPath = myTableView?.indexPathForRow(at: location) else { return nil } guard let cell = myTableView?.cellForRow(at: indexPath) else { return nil } guard let detailVC = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController else { return nil } let text = myArray[indexPath.row] detailVC.string = text detailVC.preferredContentSize = CGSize(width: 0.0, height: 300) previewingContext.sourceRect = cell.frame return detailVC } var name: String? func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { name = myArray[indexPath.row] let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController secondViewController.string = name self.navigationController?.pushViewController(secondViewController, animated: true) tableView.deselectRow(at: indexPath, animated: true) } func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) { show(viewControllerToCommit, sender: self) } } |
We populate the UITableView with an array of strings.
In the previewing protocol delegate method, we launch the detail view controller in a small window.
In the didSelectRow method of the UITableView protocols, we directly take the user to the DetailsViewController alongwith passing the data.
The code for the DetailViewController.swift is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import UIKit class DetailViewController : UIViewController{ @IBOutlet weak var myLabel: UILabel! var string: String? override func viewDidLoad() { super.viewDidLoad() if let string = string{ myLabel.text = string } } } |
The output of the above application in action is given below:
Using Preview Actions
To show Preview Actions, you need to add the following code in the ViewController that is previewed.
It is DetailsViewController in our case.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import UIKit class DetailViewController : UIViewController{ @IBOutlet weak var myLabel: UILabel! var string: String? override func viewDidLoad() { super.viewDidLoad() if let string = string{ myLabel.text = string } } override var previewActionItems : [UIPreviewActionItem] { let likeAction = UIPreviewAction(title: "Option 1", style: .default) { (action, viewController) -> Void in print("You clicked this") } let deleteAction = UIPreviewAction(title: "Option 2", style: .destructive) { (action, viewController) -> Void in print("You clicked this too") } return [likeAction, deleteAction] } } |
The output of the application with the above actions is given below:
This brings an end to this tutorial. You can download the project from the link below: