アプリグループを使用したアプリ間のデータの通信と永続化


85

iOS 8は昨日、アプリグループに関する新しいAPIを発表しました。以前は、データを共有してアプリ間で通信するのはちょっと面倒でした。それこそが、アプリグループが修正しようとしていることだと思います。

私のアプリでは、アプリグループを有効にして新しいグループを追加しましたが、その使用方法に関するドキュメントが見つかりません。ドキュメントとAPIリファレンスには、グループを追加する方法のみが記載されています。

では、アプリグループは実際に何をするつもりですか?それを使用する方法に関するドキュメントはどこかにありますか?

回答:


81

アプリグループのもう1つの利点は、NSUserDefaultsデータベースを共有できることです。これは、アプリ拡張機能(通知センターウィジェット、カスタムキーボードなど)でも機能します。

NSUserDefaultsアプリグループ内のすべてのアプリケーションでこのようにオブジェクトを初期化すると、データベースが共有されます。

Objective-C:

[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];

迅速:

NSUserDefaults(suiteName: "<group identifier>")

[NSUserDefaults standardUserDefaults]各アプリケーションのデータベースからすべてがこのデータベースに引き継がれるわけではないことに注意してください。

ドキュメントは(ベータ3のように)も正しい例を示します。

そして、データベースを同期することを忘れないでください:

[yourDefaults synchronize];

2
シミュレーターでのみ動作します(XCode 6ベータ5、iOS 8ベータ5)
iOS Dev

8
注:これをiOS 8拡張機能(キーボードなど)で使用している場合は、拡張機能のInfo.plistファイルにRequestsOpenAccess = YESが含まれていることを確認する必要があります。
キランパネサール2014

1
RequestsOpenAccess = YESを実行し、指示に従いましたが、デバイスでは機能せず、エミュレーターでは正常に機能します。デバイスに固有のものはありますか?
MAC

私と同じ問題、私は私のアプリに共有拡張機能を統合しました、それはシミュレーターで動作しますが、実際のデバイスでは動作しません、、私はRequestOpenAccess = YESを追加しましたが、動作しません、私の質問はstackoverflow.com/questions/30489894/です…
Ravi Ojha 2015年

3
@MikeRichardsはわかりませんが、正しく覚えていれば、アプリグループの前にチームIDが付けられます
サンタクロース

74

複数のアプリ間でNSUserDefaultsデータを共有する

アプリと拡張機能間、または2つのアプリ間でデフォルトを共有するには、次の手順を使用して設定にアプリグループを追加する必要があります。

  1. プロジェクトナビゲータで、*。xcodeprojファイル(上部にあるはずです)をクリックします。
  2. プロジェクトナビゲータの右側で、プロジェクトとターゲットを探します。ターゲットの下でプライマリターゲットをクリックします(ターゲットの下で最初に行う必要があります)。
  3. 上部にある[機能]タブをクリックします。
  4. [アプリグループ]セクションで、右側のスイッチをクリックしてアプリグループをオンにします。
  5. +ボタンをクリックして、group.com.company.myAppという名前のアプリグループを追加します。
  6. 他のアプリの同じ場所に移動すると、このグループを選択できるようになります。この共有データを使用するアプリごとに、このグループをオンにします。

注:Apple Developer Portal(すべての証明書、識別子、デバイス、およびプロビジョニングプロファイルを表示する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)")
}

2
ありがとう!これを行う方法を理解するためにドキュメントを検索するのに少し時間がかかりました、そして私は他の人が私が取ったステップを評価するかもしれないと思いました。
TenaciousJay 2016

詳細な説明をありがとう...!このグループを有効にするには、Apple Developer Portal(すべての証明書、識別子、デバイス、およびプロビジョニングプロファイルを表示するApple Webサイト)から証明書を作成する必要がありますか?プッシュ通知と同じです。
Arbaz Shaikh 2016

手順5を実行すると、アプリグループがAppleデベロッパポータルに追加されます。追加するためにデベロッパポータルに直接移動する必要はありません。手順5を実行した後、ポータルに移動して、ポータルが作成されていることを確認できます。
TenaciousJay 2016年

@TenaciousJayすばらしい答え。追加したいfuncアプリケーションからアプリを起動したい場合(アプリ:UIApplication、openURL url:NSURL、オプション:[文字列:AnyObject])->ブール値
Taimur Ajmal

素晴らしい答え。@TenaciousJayに感謝します。変数とその値をAppBからAppAに取得しようとしていますが、どうすればよいですか?たとえば、AppBで「riderCancelledRequest = true」の場合、AppAでこれを取得するにはどうすればよいですか?
LizG 2017年

37

私の既存のドキュメントの解釈によると、アプリケーショングループは、主に拡張機能、より具体的にはウィジェットを対象としています。ウィジェットは、アプリと共存する独自のアプリケーションバンドルです。これらは別個のアプリケーションであり、したがって独自のサンドボックスがあるため、ファイルを共有するにはアプリグループを使用する必要があります。

ヘッダーをgrepした後、APIが必要だと思いましたが、実際にはiOS7の一部として組み込まれました。

NSFileManagercontainerURLForSecurityApplicationGroupIdentifier:アプリのアプリグループをオンにするときに作成した識別子を渡すことができるメソッドがあります。

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];

ありがとう、私はあなたが拡張性について正しいと信じています。私はこのiOS7の方法についてもう少し疑わしいです、それは私にはかなり静的に見えます、iOS8はアプリ間の実際の相互作用と通信を導入しました。
streem 2014年

@JustafingerこのiOS7の方法は、共有アプリケーション間でデータを読み書きするためのURLを作成するためだけのものです。この特定の方法は、ウィジェットに対してのみ(これまでのところ)本当に役立ちますが、他の拡張機能には役立ちません。
ウェインハートマン2014年

そうですね、Appleは、プログラムでコンテナを作成したりカスタムファイルを共有したりすることなく、iOS8でこれを簡単にしたいと思っていたと思います。ドキュメントには、NSUserDefaultを使用してデータを共有できるようにする必要があると記載されています。それが私のために働いていないので、私は何かが欠けていると思います。
streem 2014年

@Justafinger私もNSUserDefaults仕事に就けませんでした。私はベータ1のバグまでチョークで書きます。
ウェインハートマン2014年

@WayneHartmanNSUserDefaultsデータベースには回避策があります。私の答えを見てください。
サンタクロース2014年

6

今日私が利用した重要な罠の1つは、次のとおりです。

多くのプロジェクトで、単一のアプリターゲットがあり、そのターゲットの構成ごとに異なるバンドル識別子が設定されているのを見ました。ここで物事は厄介になります。開発者が意図したのは、デバッグ構成用のデバッグアプリと、リリースターゲット用の本番アプリを作成することでした。

そうすると、両方のアプリがそのように設定されたときに同じNSUserDefaultsを共有します

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()

これは多くの場所で問題を引き起こします:

  1. 特別なアプリの紹介画面がユーザーに表示されたときに、キーにYESを設定したとします。他のアプリもYESと表示され、イントロは表示されません。
  2. はい、一部のアプリはユーザーのデフォルトでoAuthトークンも保存します。とにかく...実装に応じて、アプリはトークンがあることを認識し、間違ったトークンを使用してデータの取得を開始します。これが奇妙なエラーで失敗する可能性が高いです。

一般に、この問題の解決策は、デフォルトのキーの前に現在の構成を構築することです。構成に異なるバンドル識別子を設定することにより、実行時に構成を簡単に検出できます。次に、からバンドル識別子を読み取ります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

8
共有UserDefaultsにすべてのデータを混在させるため、問題が発生します。NSUserDefaults.standardUserDefaults()共有してはいけないデータに使用する必要があります。
ダニエル

2

保存するには

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.