[Swift] iOS の共有メニューに追加できるアプリを作る(その3:ContainingApp と App Extensionのデータ共有)

     

TAGS:

⌛️ 2 min.
今回は、Containing App と App Extension とのデータのやり取りを説明します。

[Swift] iOS の共有メニューに追加できるアプリを作る(その 2:HostAppからデータを受け取るまで)

[Swift] iOS の共有メニューに追加できるアプリを作る(その1:共有メニューにアプリが表示されるまで)

例題の仕様

Host App から渡された画像ファイルを Containing App の背景に設定するようなアプリを作ってみます。

課題:Containing App と App Extension は、別アプリ

基本的に別アプリのような扱いとなります。(具体的には、別々の Sandbox が割り当てられるため、直接のやりとりができません)

何が問題かというと、App Extension が受け取ったデータをそのまま、Containing App に渡すことができないという点です。

例えば、UserDefaults にデータを保存しての受け渡しもできませんし、CoreDataを使ったやりとりも同様です。

解決法:App Groupを使う

App Group は、やりとりしたい Containing App と App Extension の両方で設定する必要があります。

Group 名は、”group”で始まる必要があり、通常は、Bundle Identifierと同様のcom.XXX.YYY.ZZZ のような名称を指定します。

App(Containing App)側の設定

Group setting for App

App Extension 側の設定

GroupSetting for Extension




App Group の共有リソースへのアクセス

UserDefaults を共有リソースとしたデータ共有

UserDefaults 経由で共有する時には、普段使っている UserDefaults.standard 経由のアクセスではなく、App Group名を使用したアクセスが必要となります。

App Group 名が、”group.com.smalldesksoftware.shareapp” とすると、以下のように、init(suiteName:)を使ってアクセスします。

コード


let defaults = UserDefaults.init(suiteName: "group.com.smalldesksoftware.shareapp")

App Extension(データを渡す側)では、以下のようなコードでデータを保存します。

コード


if let defaults = UserDefaults.init(suiteName: "group.com.smalldesksoftware.shareapp") {
    defaults.set(true, forKey: "NeedToImportFromExtension")
}

Containing App(データを受け取る側)では、以下のようなコードでデータを受け取ることができます。

コード


if defaults.bool(forKey: "NeedToImportFromExtension") {
    print("need to import something from shared info")
    defaults.set(false, forKey: "NeedToImportFromExtension")
}

UserDefaults では、大きなデータを保存することを推奨されていません。

ということで、UserDefaults 以外にも、App Group が設定されていることによりリソースを共有する方法があります。

FileSystem を使った共有リソースアクセス

containerURL(forSecurityApplicationGroupIdentifier:)を使って、アクセスします。

コード


let shareURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.smalldesksoftware.shareapp")

あとは、適当なファイル名等を追加してアクセスします。

App Extension(データを渡す側)では、以下のようなコードでデータを保存します。

コード


if let shareURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.smalldesksoftware.shareapp") {
  let targetURL = shareURL.appendingPathComponent("image.jpg")
  try? FileManager.default.copyItem(at: fileURL, to: targetURL)
}

Containing App(データを受け取る側)では、以下のようなコードでデータを受け取ることができます。

コード


if let shareURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.smalldesksoftware.shareapp") {
  imageURL = shareURL.appendingPathComponent("image.jpg")
  // process imageURL
}




まとめ:Containing App と App Extension のデータ共有

共有には、UserDefautls と FileSystem を使えます。

FileSystem が使えるということは、CoreData 等も使えるということです。

ただし、Containing App と App Extension の競合は、自分で管理する必要があります。

説明は以上です。




1 COMMENT

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です