Help us understand the problem. What is going on with this article?

Swiftで3D Touch

More than 1 year has passed since last update.

3D Touchについて

実装に必要なもの

シミュレータで見る場合

・Xcode7.3以上
・iPhone 6s/6s Plus以降
・iOS9以上
・Force touchが使えるトラックパッドが必要

実機で見る場合

・Xcode7.1以上
・iPhone 6s/6s Plus以降
・iOS9以上

デフォルトでは3D Touchできるようになっているが、無効にしている場合は
設定>一般>アクセシビリティ> 3Dタッチ
で設定し直してください。
因みにここで感度を変える事ができ、3D Touchのテストもできます。

用語一覧 Appleの3D Touch

Peek And Pop(軽くプレス時に表示される) Peek Quick Actions(Peek時に上にスワイプして出てくる) Home Screen Quick Action(アイコンをプレスすることで現れるアクション)

UIViewControllerPreviewingDelegateプロトコル

Peekとして表示される

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {}

とPopする直前に呼ばれる処理

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {}`    

が必須です。

ビューをPeek and Popの対象にする

if self.traitCollection.forceTouchCapability == UIForceTouchCapability.Available {
  registerForPreviewingWithDelegate(self, sourceView: view)
}

実装方法

extension ViewController: UIViewControllerPreviewingDelegate {
  func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
      let secondVC = storyboard?.instantiateViewControllerWithIdentifier("secondVC") as! SecondViewController
      // Peek(軽くプレス)で呼ばれるViewController
      return secondVC
  }
  func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
      // viewControllerToCommitはPeek時にセットされたViewController
      // 今回はNavigationViewControllerを継いでるのでshowViewControllerを使うがそうじゃない場合はpresentViewControllerでモーダル表示
      showViewController(viewControllerToCommit, sender: self)

      // Peekとは違う画面をPopで表示する事もできる
      // let thirdVC = storyboard?.instantiateViewControllerWithIdentifier("thirdVC") as! ThirdViewController
      // showViewController(thirdVC, sender: self)
  }

上記のコードの説明
1. previewingContext
プレビューのコンテキストオブジェクトで
previewingContextにはsourceViewがあります。

if previewingContext.sourceView is UIButton {
    // do something
  } else if previewingContext.sourceView is UILabel {
    // do something
  }

こんなことができる。

2.location
tableView.indexPathForRowAtPoint(location)
TableViewを使っている時のどのセルをプレスされているかが取得できる

3.ViewControllerではなく、nilを返す事で無効にできる

Home Screen Quick Action

実装方法

やり方は2通りあり、
・info.plistに追加する方法
・コードで追加する方法
があります。

info.plistで実装
<key>UIApplicationShortcutItems</key>
    <array>
        <dict>
            <key>UIApplicationShortcutItemIconType</key>
            <string>UIApplicationShortcutIconTypePlay</string>
            <key>UIApplicationShortcutItemTitle</key>
            <string>SEARCH</string>
            <key>UIApplicationShortcutItemType</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER).Search</string>
        </dict>
        <dict>
            <key>UIApplicationShortcutItemIconType</key>
            <string>UIApplicationShortcutIconTypeAdd</string>
            <key>UIApplicationShortcutItemTitle</key>
            <string>ADD</string>
            <key>UIApplicationShortcutItemType</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER).Add</string>
        </dict>
    </array>

これでホームアイコンをプレスするとADDとPLAYが表示される。

コードで実装する方法
let shortcut = UIMutableApplicationShortcutItem(type: "UIApplicationShortcutIconTypePlay", localizedTitle: "SEARCH", localizedSubtitle: "再生する", icon: UIApplicationShortcutIcon(type: .Play), userInfo: nil)
            UIApplication.sharedApplication().shortcutItems = [shortcut]

コードとplistでの実装の違い
コードで実装する場合、アプリをインストールしてから一度アプリを起動する必要がある。
info.plistで実装する場合、アプリをインストール直後から実装されるが、動的に変えることができない。

下の画像は3D Touch の Home Screen Quick Actions に対応するから引用

iOS9.0で使えるアイコン達

つまり上記のコードではADDとPLAYが表示されます。

この中にアイコンがない場合は(自作でやりたい場合)

<dict>
    <key>UIApplicationShortcutItemIconFile</key>
    <string>(画像)</string>
    <key>UIApplicationShortcutItemTitle</key>
    <string>SEARCH</string>
    <key>UIApplicationShortcutItemType</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER).Search</string>
</dict>

UIApplicationShortcutItemIconFileを設定するとUIApplicationShortcutItemIconTypeは強制的に適用されなくなるので意味なくなります。

アイコンをタップ時に通知されるメソッドはAppDelegateにあり、

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void)

で取得する事ができ、実装方法としては

extension AppDelegate {

    private enum ShortcutItemType: String {
        case Play

        init?(shortcutItem: UIApplicationShortcutItem) {
            guard let last = shortcutItem.type.componentsSeparatedByString(".").last else { return nil }
            self.init(rawValue: last)
        }

        var type: String {
            return NSBundle.mainBundle().bundleIdentifier ?? "" + ".\(rawValue)"
        }
    }

    func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
        guard let itemType = ShortcutItemType(shortcutItem: shortcutItem) else { return }
        switch itemType {
        case .Play:
            // do something
            break
        }
    }

}

こんな感じで取得する事ができます。

iOS Human Interface Guidelines

  • PeekのViewでボタンの要素などをおくのはやめる。
    ユーザーがタップしようとして指を離したときに、Peekが消えるので

  • Peekだけというのは避ける
    Peek And Popは一貫して採用、Peekしかできない場合ユーザーのデバイスに問題があるのではないかと思われる為

  • Popを表示するためのアクションボタンをPeek quick actionsのボタンとして出すのはやめる。
    表示するために深くプレスするので。

  • Peek quick actionsのアクションでしかできないことにしないこと
    必ずしも全てのデバイスが3D Touchをサポートしてるとは限らないので

  • 適切なアクションボタンを用意しよう

  • Peekingと全く同じ編集ボタンを用意するのはやめよう

kusumotoa
宜しくお願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away