iOS 8は昨日、App Groupsに関する新しいAPIを明らかにしました。以前はデータを共有してアプリ間で通信するのはちょっと面倒でしたが、App Groupsがそれを修正しようとしているのはまさにそれだと思います。
私のアプリでは、アプリグループを有効にして新しいグループを追加しましたが、使用方法に関するドキュメントが見つかりません。ドキュメントとAPIリファレンスには、グループの追加方法のみが記載されています。
それでは、App Groupsは実際に何をするつもりなのでしょうか?使用方法に関するドキュメントはどこかにありますか?
アプリグループのもう1つの利点は、NSUserDefaults
データベースを共有できることです。これは、App Extensions(通知センターウィジェット、カスタムキーボードなど)でも機能します。
アプリグループ内のすべてのアプリケーションでこのようにNSUserDefaults
オブジェクトを初期化すると、データベースを共有します。
Objective-C:
[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];
迅速:
NSUserDefaults(suiteName: "<group identifier>")
各アプリケーションの[NSUserDefaults standardUserDefaults]
データベースのすべてがこのデータベースに引き継がれないことに注意してください。
documentation も正しい例を示しています(ベータ3以降)。
データベースを同期することを忘れないでください:
[yourDefaults synchronize];
複数のアプリ間でNSUserDefaultsデータを共有する
アプリと拡張機能間、または2つのアプリ間でデフォルトを共有するには、次の手順を使用して設定にアプリグループを追加する必要があります。
注:Apple開発者ポータル(すべての証明書、識別子、デバイス、およびプロビジョニングプロファイルを表示するApple Webサイト)にアクセスすると、 [識別子]> [アプリグループ]に移動すると、この新しいアプリグループが表示されます。
データを保存するには:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")!
userDefaults.setObject("user12345", forKey: "userId")
userDefaults.synchronize()
データを取得するには:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
print("User Id: \(testUserId)")
}
既存のドキュメントの私の解釈によると、アプリケーショングループは主に拡張機能、より具体的にはウィジェットを対象としています。ウィジェットは、アプリと共存する独自のアプリケーションバンドルです。これらは個別のアプリケーションであり、独自のサンドボックスを持っているため、ファイルを共有するにはアプリグループを使用する必要があります。
ヘッダーをgrepしてから、必要なAPIが見つかったと思いますが、実際にはiOS 7の一部として組み込まれました。
NSFileManager
にはメソッドがありますcontainerURLForSecurityApplicationGroupIdentifier:
アプリのアプリグループを有効にするときに作成した識別子を渡すことができます:
NSURL *containerURL = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];
今日私がタップした重要なトラップの1つは次のとおりです。
多くのプロジェクトで、1つのアプリターゲットと、そのターゲットの構成ごとに異なるバンドル識別子が設定されているのを見ました。ここでは物事が面倒になります。開発者が意図したのは、デバッグ設定用のデバッグアプリとリリースターゲット用の本番アプリを作成することでした。
そのように設定すると、両方のアプリが同じように設定されたときに同じNSUserDefaultsを共有します
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()
これは多くの場所で問題を引き起こします:
この問題の一般的な解決策は、デフォルトのキーの前に構築された現在の構成を追加することです。構成に異なるバンドル識別子を設定することにより、実行時に構成を簡単に検出できます。次に、NSBundle.mainBundle()
からバンドル識別子を読み取ります。同じバンドル識別子がある場合は、次のような異なるプリプロセッサマクロを設定する必要があります
#ifdef DEBUG
NSString* configuration = @"debug";
#Elif RELEASE
NSString* configuration = @"release";
#endif
Swiftでは、ほとんど同じように見えます。
#if DEBUG
let configuration = "debug"
#elseif RELEASE
let configuration = "release"
#endif
保存するために
let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()