App Groupという仕組みを使って、アプリ同士のファイル共有を試してみました。
ちなみにApp Groupは自分が開発したアプリ間でないとデータ共有できないので注意が必要です。
下記事ではUserDefaultsの共有を試したので、今回はファイル共有を試してみようと思います。
テキストの共有
前回同様、まずはプロジェクトを2つ作成します。
次にそれぞれのプロジェクトのCapabilitiesからAppGroupをONにします。
有効化したら新しいApp Groupを作成します。
+ボタンから、AppGroupを追加してください。
これでAppGroupを使う準備が完了しました。
次は共有処理を書いていきます。
まずは片方のアプリからデータ保存します。
MyApp1のAppDelegate.swiftを以下のようにして下さい。
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myapp")?.appendingPathComponent("file_name") { try? "MyText".write(to: url, atomically: true, encoding: .utf8) } return true } }
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:)
がApp Group用のURLを生成するメソッドです。
このURLに保存されたファイルは、他アプリでも取得する事ができます。
ちなみにこのメソッドに設定してないIDを入れるとnilが返ってきます。
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.dummy") // → nil
アプリを実行してテキストを保存します。
続けて別アプリでファイルの読み込みができるかも調べてみます。
MyApp2のAppDelegate.swiftを以下のように修正して下さい。
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myapp")?.appendingPathComponent("file_name") { print(try? String(contentsOf: url)) } return true } }
実行すると、MyApp1で保存したテキストがMyApp2で取得できている事が分かります。
App Group用URLの中身
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myapp")
ですが、パスは下のようなものになります。
file:///Users/xxxxx(ユーザー名)/Library/Developer/CoreSimulator/Devices/xxxxxx(ランダムな文字列)/data/Containers/Shared/AppGroup/xxxxxx(ランダムな文字列)/
普通にファイルを保存する時のフォルダは下URLです。
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true).first // → /Users/xxxxx(ユーザー名)/Library/Developer/CoreSimulator/Devices/xxxxxx(ランダムな文字列)/data/Containers/Data/Application/xxxxxx(ランダムな文字列)/Documents
見比べてみるとContainers以下が違っている事が分かります。
data/Containers/Shared/AppGroup/xxxxxx(ランダムな文字列)/ data/Containers/Data/Application/xxxxxx(ランダムな文字列)/Documents
画像の共有
最後に画像の共有も試してみようと思います。
MyApp1のAppDelegateを下のように修正します。
テキストを保存した時と同じように、画像をストレージに保存します。
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.clhs09")?.appendingPathComponent("image") { try? UIImageJPEGRepresentation(#imageLiteral(resourceName: "image"), 1.0)?.write(to: url) } return true } }
次にMyApp2で画像の取得をします。
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.clhs09")?.appendingPathComponent("image") { print(try? Data(contentsOf: url)) } return true } }
実行するとデータの取得に成功したことが分かります。