[廃止予定]ユーザー体験を向上させるために、今すぐあなたのiOSアプリに3D TOUCH機能を追加しましょう(Swift)
iOS 3D TOUCH の応用
[廃止] 2020/06/14
iPhone 11以降のモデルでは3D Touch機能が廃止され、代わりにHaptic Touchが採用されており、実装方法も異なります。
先日、プロジェクト開発の合間に多くのiOSの面白い機能を探求しました: CoreML 、 Vision 、 Notification Service Extension 、Notification Content Extension、Today Extension、Core Spotlight、Share Extension、SiriKit(一部は記事にまとめ済み、その他はお楽しみに🤣)
その中でも今日の主役は:3D Touch機能
この機能は iOS 9/iPhone 7以降 にサポートされ始め、私自身がiPhone 6からiPhone 8に乗り換えて初めてその便利さを実感しました!
3D TouchはAPP内で以下の2つの機能を実装できます:

- Preview ViewController プレビュー機能 — 結婚吧APP

- 3D TouchショートカットAPPショートカット起動機能
最初の項目は最も広く使われ、効果も高いものです(Facebook:ニュースフィードの内容プレビュー、Line:メッセージのチラ見)。二番目のAPPショートカット起動は、現在のデータでは利用者が少ないため、最後に説明します。
1. Preview ViewController プレビュー機能:
機能のデモは上の図1のように、ViewControllerのプレビュー機能をサポートしています。
-
3D Touchで強く押すと背景がぼやける
-
3D Touchで強く押すとViewControllerのプレビューウィンドウが表示される
-
3D Touchで強く押すとViewControllerのプレビューウィンドウが表示され、上にスワイプすると下部にオプションメニューを追加できる
-
3D Touchで強く押して離すとウィンドウに戻る
-
3D Touchで強く押してからさらに力を入れて目的のViewControllerに入る
ここでは A:リストウィンドウ 、 B:ターゲットウィンドウ に分けて実装するコードをそれぞれ示します:
B内では現在がプレビューか実際にこの画面に入っているかを判別する方法がないため、まず値を渡すためのProtocolを作成して判定します。
protocol UIViewControllerPreviewable {
var is3DTouchPreview:Bool {get set} // 3D Touchプレビューかどうか
}
これでBの中で以下の判定ができるようになります:
class BViewController:UIViewController, UIViewControllerPreviewable {
var is3DTouchPreview:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
if is3DTouchPreview {
// プレビュー画面の場合...例:全画面表示にする、ツールバーを隠す
} else {
// 通常モードの場合はそのまま表示
}
}
A:リストビューは UITableView または UICollectionView です:
class AViewController:UIViewController {
//3D Touch対応のViewを登録
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 {
//3D Touchを離した後の処理
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
//これから直接遷移するため、ViewControllerのプレビューモードパラメータを解除:
if var viewControllerToCommit = viewControllerToCommit as? UIViewControllerPreviewable {
viewControllerToCommit.is3DTouchPreview = false
}
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
//3D TouchのCell位置と表示するViewControllerを制御
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
//現在のタップ位置のindexPath/セルの実体を取得
//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 }
//表示したいViewController
let targetViewController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier")
//背景のぼかし時に残す領域(通常はタップ位置)、図1参照
previewingContext.sourceRect = cell.frame
//3D Touchウィンドウのサイズ、デフォルトは自動調整で変更不要
//変更する場合は:targetViewController.preferredContentSize = CGSize(width: 0.0, height: 0.0)
//プレビュー中のViewControllerに現在プレビューモードであることを通知:
if var targetViewController = targetViewController as? UIViewControllerPreviewable {
targetViewController.is3DTouchPreview = true
}
//nilを返すと何も動作しない
return nil
}
}
注意してください!3D Touchを有効にするViewの登録は“viewDidLoad”ではなく、traitCollectionDidChange内で行う必要があります(こちらの記事を参照してください)。
どこに追加するかについて、多くのトラブルを経験しました。ネット上の情報ではviewDidLoadに書く場合もあれば、cellForItem内に書く場合もありますが、どちらも時々動作しなかったり、一部のセルだけが動作しない問題が発生しました。

付図1 背景ぼかし保持領域のイメージ図
もし上にスワイプして下にオプションメニューを追加する必要がある場合は、B の中に追加してください。BはB、BはBですよ!

override var previewActionItems: [UIPreviewActionItem] {
let profileAction = UIPreviewAction(title: "店舗情報を見る", style: .default) { (action, viewController) -> Void in
// タップ後の操作
}
return [profileAction]
}
空の配列を返すことで、この機能を使用しないことを示します。
完了!
2. APP ショートカット起動
第一歩
info.plist に UIApplicationShortcutItems パラメータを追加し、タイプは Array に設定する
そして、その中にメニュー項目(Dictionary)を追加し、キーと値の設定は以下の通りです:
-
[必須] UIApplicationShortcutItemType : 識別文字列で、AppDelegateで判定に使用します
-
[必須] UIApplicationShortcutItemTitle : オプションのタイトル
-
UIApplicationShortcutItemSubtitle : オプションのサブタイトル

- UIApplicationShortcutItemIconType : システムアイコンを使用する

参考元は こちらの記事 です。
-
UIApplicationShortcutItemIconFile : カスタムアイコンを使用(サイズ:35x35、単色)、UIApplicationShortcutItemIconTypeとどちらか一方を使用してください
-
UIApplicationShortcutItemUserInfo : 追加情報の詳細例 EX: [id:1]

私の設定は上の図の通りです
第二ステップ
AppDelegateに処理用の関数を追加する
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)
}
完了!
結論
APPに3D Touch機能を追加するのは難しくなく、ユーザーにとっても親切に感じられます❤;操作デザインと組み合わせてユーザー体験を向上させることができます;しかし現時点では上述の2つの機能しかなく、iPhone 6s以下やiPad、iPhone XRは3D Touchをサポートしていないため、実際にできる機能はさらに限られています。あくまで補助的に体験を向上させることが主な目的となります。
p.s.

もし細かくテストすると、上記の効果は、CollectionViewのスクロール中に一部の画像が画面外に出ているときに押し込むと、上記の状況が発生することがわかります😅
Post MediumからZMediumToMarkdownによって変換されました。



コメント