【SwiftUI】静的 Home Screen Quick Actions(アプリアイコン長押しメニュー)

SwiftUI

Home Screen Quick Actionsの実装方法についてです。

Home Screen Quick Actionsではアプリアイコンをロングタップする事で表示されるコンテキストメニューに項目を追加する事が出来ます。
この項目から起動する事で、起動時に特定の処理をさせたり画面を指定して起動する事が出来ます。

静的なものと動的なものがありますが、今回は静的なものを扱います。
※私のアプリでは静的なもので十分だった為。後日動的なものも試して記事にする予定です。

先に断っておきますが、AppDelegate(SceneDelegate)を使用します。
SwiftUIのみで完結しているわけではないのでご了承ください。
※SwiftUIのみで簡単に扱う方法があればTwitterの方に連絡いただけるととても嬉しいです。

Home Screen Quick Actionsとは

Home Screen Quick Actionsとは、アプリをロングタップした時に表示されるメニューへ追加できる機能です。
アプリの削除やホーム画面を編集と表示される個所に追加する事が出来ます。

起動時に処理を追加したり、特定の画面を指定して開く場合などに使われています。
Safariではブックマークを開いたり、新規タブを開く、
メールでは全受信の画面を開いたり、新規メール画面を開いたりなどで使われています。
他にも、データが蓄積して動作が重くなった場合に、リセットして起動するなどの使い方も出来ます。

実装方法

今回は静的なものを扱うので、以下の2つがポイントとなります。

  • Info.plistへの追記
  • AppDelegateの追加

静的なものの場合は、メニューへ追加される内容はInfo.plistへ記述します。
コード側では値を受け取って処理をするだけで、メニューの表示自体の実装はありません。

メニューで選択された値を受ける際にAppDelegateを使用します。
現在のSwiftUIではAppDelegateは標準では実装されていませんが、
他に方法がないのでAppDelegateを追加することになります。

Info.plistへの追記

最近のXcodeは標準でinfo.plistファイルを生成しません。
プロジェクトファイルに含まれているので、プロジェクトの設定からTAGETSを選択してInfoのタブを選択してください。

適当な所を右クリックし、Add Rowを選択してHome Screen Shortcut Itemsを追加してください。
するとInfo.plistが生成されるので、以降はそちらに追記して行きます。

Home Screen Shortcut Items以下にItem0があり、その下にTitleとShortcut Item Typeがあります。
Titleにはメニューの表示名を、Shortcut Item Typeにはコード内で使う識別名を設定してください。
最低限この2つがあればOKです。

AppDelegateの追加

Shortcut Item Typeを受け取る為にAppDelegateを実装して行きます。

import SwiftUI

@main
struct HomeScreenQuickActionTestApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate{
    
    func application(
        _ application: UIApplication,
        configurationForConnecting connectingSceneSession: UISceneSession,
        options: UIScene.ConnectionOptions
    ) -> UISceneConfiguration {

        print(options.shortcutItem?.type) //これがShortcut Item Type

        return UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
    }
    
}

@UIApplicationDelegateAdaptorでAppDelegateを使用します。
applicationメソッドの引数にあるoptionsに含まれるので、
typeを確認して対応した処理を行なってい行きます。

起動時のみの場合はこれでOKです。

起動済みのアプリでも使用したい場合はSceneDelegateも使用します。

class AppDelegate: NSObject, UIApplicationDelegate{
    
    func application(
        _ application: UIApplication,
        configurationForConnecting connectingSceneSession: UISceneSession,
        options: UIScene.ConnectionOptions
    ) -> UISceneConfiguration {
        
//        print(options.shortcutItem?.type) //これがShortcut Item Type
        
        let config = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        config.delegateClass = SceneDelegate.self
        return config
    }
    
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate{
    
    //起動時にも実行される、ここで処理を行う場合はAppDelegateで処理をしない。
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        print(connectionOptions.shortcutItem?.type) //これがShortcut Item Type
    }

    //起動後はこちらで受け取る
    func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        print(shortcutItem.type) //これがShortcut Item Type
        completionHandler(true)
    }
}

AppDelegateにSceneDalegateを指定するコードを追加しました。

sceneはSceneがConnectされた際に実行されます。
applicationと異なる点は、iPad OSでWindowを複数起動する際にも呼ばれる事です。
アプリ起動時にapplicationとsceneは両方呼ばれるので、
どちらか一方のみでShortcutの処理をしてください。

iOSであればどちらでも問題ありませんし、iPad OSでも現状はショートカットを使用すると既存のWindowで実行されるのでどちらでも問題はありません。
今後のことを考えるとSceneDalegateを実装したならば一応sceneの方が良いとは思います。

windowSceneは起動後に、ショートカットを使用してバックグラウンドのアプリをアクティブにする際に呼ばれます。

なおSceneDalegateの追加方法が知っているものと異なるかもしれませんが、この方法でも大丈夫です。
詳しくは以下の記事をご覧ください。

【SwiftUI】SceneDelegateを使う方法(2パターン)
SwiftUIでは2系からSceneDelegateが使用されなくなりました。しかし自分で追加することでSceneDelegateの使用は可能です。 調べるとおおよそ2パターン見受けられるのでまとめておきます。 共通部分 AppとScene...

コメント

タイトルとURLをコピーしました