[Deprecated] Enhance User Experience by Adding 3D TOUCH to Your iOS APP (Swift)
iOS 3D TOUCH Application
[Deprecated] 2020/06/14
3D Touch functionality has been removed in iPhone 11 and later versions; it has been replaced by Haptic Touch, which is implemented differently.
Some time ago, during a break in project development, I explored many interesting iOS features: CoreML, Vision, Notification Service Extension, Notification Content Extension, Today Extension, Core Spotlight, Share Extension, SiriKit (some have been organized into articles, others are coming soon 🤣)
Among them is today’s main feature: 3D Touch
This feature, supported since iOS 9/iPhone 7, only became useful to me after I upgraded from an iPhone 6 to an iPhone 8!
3D Touch can implement two features in an APP, as follows:
- Preview ViewController Preview Function — Wedding App
- 3D Touch Shortcut APP Shortcut Launch Function
The first feature is the most widely used and effective (Facebook: content preview in news feed, Line: sneak peek at messages), while the second feature, APP Shortcut Launch, is less commonly used based on data, so it will be discussed last.
1. Preview ViewController Preview Function:
As shown in the first image above, the ViewController preview function supports:
- Background blur when 3D Touch is pressed
- ViewController preview window pops up when 3D Touch is pressed
- ViewController preview window pops up when 3D Touch is pressed, with an option menu at the bottom when swiped up
- Return to the window when 3D Touch is released
- Enter the target ViewController with a harder press after 3D Touch
Here, we will list the code to implement in A: List View and B: Target View separately:
Since there is no way to determine whether the current view is a preview or an actual entry in B, we first create a Protocol to pass values for judgment:
1
2
3
protocol UIViewControllerPreviewable {
var is3DTouchPreview: Bool { get set }
}
This way, we can make the following judgments in B:
1
2
3
4
5
6
7
8
9
10
class BViewController:UIViewController, UIViewControllerPreviewable {
var is3DTouchPreview:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
if is3DTouchPreview {
// If it is a preview window... for example: full screen, hide the toolbar
} else {
// Display normally in full mode
}
}
A: List window, can be UITableView or UICollectionView:
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
46
47
48
49
50
class AViewController:UIViewController {
// Register the View that can 3D Touch
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.forceTouchCapability == .available {
// TableView:
registerForPreviewing(with: self, sourceView: self.TableView)
// CollectionView:
registerForPreviewing(with: self, sourceView: self.CollectionView)
}
}
}
extension AViewController: UIViewControllerPreviewingDelegate {
// Handling after 3D Touch is released
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
// Now we need to navigate to the page directly, so cancel the preview mode parameter of the ViewController:
if var viewControllerToCommit = viewControllerToCommit as? UIViewControllerPreviewable {
viewControllerToCommit.is3DTouchPreview = false
}
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
// Control the position of the 3D Touch Cell, the ViewController to be displayed
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
// Get the current indexPath/cell entity
// TableView:
guard let indexPath = TableView.indexPathForRow(at: location), let cell = TableView.cellForRow(at: indexPath) else { return nil }
// CollectionView:
guard let indexPath = CollectionView.indexPathForItem(at: location), let cell = CollectionView.cellForItem(at: indexPath) else { return nil }
// The ViewController to be displayed
let targetViewController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier")
// Retain area when background is blurred (usually the click location), see Figure 1
previewingContext.sourceRect = cell.frame
// 3D Touch window size, default is adaptive, no need to change
// To modify, use: targetViewController.preferredContentSize = CGSize(width: 0.0, height: 0.0)
// Inform the previewing ViewController that it is currently in preview mode:
if var targetViewController = targetViewController as? UIViewControllerPreviewable {
targetViewController.is3DTouchPreview = true
}
// Returning nil has no effect
return nil
}
}
Note! The registration of the 3D Touch View should be placed in traitCollectionDidChange instead of “viewDidLoad” ( refer to this content )
I encountered many issues regarding where to place it. Some sources on the internet suggest viewDidLoad, while others suggest cellForItem. However, both places may occasionally fail or cause some cells to malfunction.
Figure 1 Background Blur Reserved Area Diagram
If you need to add an options menu after swiping up, please add it in B. It’s B, B, B!
1
2
3
4
5
6
override var previewActionItems: [UIPreviewActionItem] {
let profileAction = UIPreviewAction(title: "View Merchant Info", style: .default) { (action, viewController) -> Void in
// Action after clicking
}
return [profileAction]
}
Returning an empty array indicates that this feature is not used.
Done!
2. APP Shortcut Launch
Step 1
Add the UIApplicationShortcutItems parameter in info.plist, type Array
And add menu items (Dictionary) within it, with the following Key-Value settings:
- [Required] UIApplicationShortcutItemType: Identifier string, used for judgment in AppDelegate
- [Required] UIApplicationShortcutItemTitle: Option title
- UIApplicationShortcutItemSubtitle: Option subtitle
- UIApplicationShortcutItemIconType: Use system icon
Referenced from this article
- UIApplicationShortcutItemIconFile: Use custom icon (size: 35x35, single color), use either this or UIApplicationShortcutItemIconType
- UIApplicationShortcutItemUserInfo: Additional information EX: [id:1]
My settings as shown above
Step 2
Add the handling function in AppDelegate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
var info = shortcutItem.userInfo
switch shortcutItem.type {
case "searchShop":
//
case "topicList":
//
case "likeWorksPic":
//
case "marrybarList":
//
default:
break
}
completionHandler(true)
}
Done!
Conclusion
Adding 3D Touch functionality to the APP is not difficult and users will find it very considerate ❤; it can be combined with design operations to enhance user experience. However, currently, only the two functions mentioned above can be implemented, and since iPhone 6s and below/iPad/iPhone XR do not support 3D Touch, the actual functionalities that can be done are even fewer, mainly serving as an aid to enhance the experience.
p.s.
If you test carefully enough, you will notice the above effect. When part of the image in the CollectionView has already slid out of the screen, pressing it will result in the above situation 😅
If you have any questions or feedback, feel free to contact me.
===
===
This article was first published in Traditional Chinese on Medium ➡️ View Here