web-dev-qa-db-fra.com

Communication et conservation de données entre des applications avec des groupes d'applications

iOS 8 a révélé une nouvelle API hier concernant les groupes d'applications. Avant, c'était un peu compliqué de partager des données et de communiquer entre des applications et je pense que c'est précisément ce que les groupes d'applications sont censés corriger.

Dans mon application, j'ai activé les groupes d'applications et ajouté un nouveau groupe, mais je ne trouve aucune documentation sur son utilisation. La documentation et les références d'API indiquent uniquement comment ajouter un groupe.

Alors, qu'est-ce que les groupes d'applications ont vraiment l'intention de faire? Existe-t-il une documentation quelque part sur son utilisation?

79
streem

Un autre avantage de App Groups est la possibilité de partager une base de données NSUserDefaults. Cela fonctionne également pour les extensions d'application (widgets du centre de notification, claviers personnalisés, etc.).

Initialisez votre objet NSUserDefaults comme ceci dans toutes les applications du groupe d'applications et elles partageront la base de données:

Objectif c:

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

Rapide:

NSUserDefaults(suiteName: "<group identifier>")

Gardez à l'esprit tout de la [NSUserDefaults standardUserDefaults] base de données pour chaque application ne sera pas transférée dans cette base de données.

Le documentation donne également un exemple correct (à partir de la version bêta 3).

Et n'oubliez pas de synchroniser la base de données:

[yourDefaults synchronize];
79
Santa Claus

Partage des données NSUserDefaults entre plusieurs applications

Pour avoir les valeurs par défaut partagées entre une application et une extension ou entre 2 applications, vous devez ajouter un groupe d'applications dans vos paramètres en procédant comme suit:

  1. Dans le Navigateur de projet, cliquez sur le fichier * .xcodeproj (qui devrait être en haut).
  2. À droite du navigateur de projet, recherchez Projet et objectifs. Sous cibles, cliquez sur votre cible principale (devrait être la première chose sous cibles).
  3. Vers le haut, cliquez sur l'onglet Capacités.
  4. Dans la section Groupes d'applications, cliquez sur le bouton situé à droite pour activer les groupes d'applications.
  5. Cliquez sur le bouton + et ajoutez un groupe d'applications nommé group.com.company.myApp .
  6. Allez au même endroit dans vos autres applications et ce groupe devrait maintenant être disponible pour la sélection. Activez ce groupe pour chaque application qui utilisera ces données partagées.

Remarque: Si vous accédez au portail de développeur Apple (le site Web Apple qui affiche tous vos certificats, identifiants, Profils et profils de provisioning) et allez dans Identifiants> Groupes d’applications vous devriez voir ce nouveau groupe d’applications.

Pour stocker des données:

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

pour récupérer des données:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
  print("User Id: \(testUserId)")
}
69
TenaciousJay

Selon mon interprétation de la documentation existante, les groupes d’applications sont principalement destinés aux extensions, plus spécifiquement aux widgets. Les widgets sont leur propre ensemble d'applications qui coexistent avec votre application. Comme elles constituent une application distincte et ont donc leur propre sandbox, vous devrez utiliser des groupes d'applications pour partager des fichiers.

Après un peu d’en-tête, je pense avoir trouvé l’API nécessaire, mais elle a été intégrée à iOS 7.

NSFileManager a une méthode dessus containerURLForSecurityApplicationGroupIdentifier: où vous pouvez transmettre l'identifiant créé lors de l'activation des groupes d'applications pour vos applications:

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

Un piège important que j'ai exploité aujourd'hui est le suivant:

Dans de nombreux projets, j'ai vu une cible d'application unique et avec différents identificateurs d'ensembles définis pour chaque configuration de cette cible. Ici, les choses se gâtent. Les développeurs souhaitaient créer une application de débogage pour la configuration de débogage et une application de production pour la cible de publication.

Si vous le faites, les deux applications partagent les mêmes NSUserDefaults lorsqu’elles sont configurées comme suit.

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

Cela pose des problèmes à plusieurs endroits:

  1. Imaginez que vous définissiez YES pour une clé lorsqu'un écran d'application spécial a été présenté à l'utilisateur. L'autre application lira maintenant aussi OUI et ne montrera pas l'intro.
  2. Oui, certaines applications stockent également des jetons oAuth dans leurs valeurs utilisateur par défaut. Quoi qu'il en soit ... En fonction de la mise en œuvre, l'application reconnaîtra qu'il existe un jeton et commencera à récupérer les données à l'aide du mauvais jeton. haut que cela va échouer avec des erreurs étranges.

La solution à ce problème en général consiste à préfixer les clés par défaut avec la configuration actuelle construite. Vous pouvez facilement détecter la configuration au moment de l'exécution en définissant différents identificateurs d'ensembles pour vos configurations. Ensuite, il suffit de lire l'identifiant de paquet dans NSBundle.mainBundle(). Si vous avez les mêmes identifiants de lot, vous devez définir différentes macros de préprocesseur telles que

#ifdef DEBUG
  NSString* configuration = @"debug";
#Elif RELEASE
  NSString* configuration = @"release";
#endif

Dans Swift, il se ressemblera presque:

#if DEBUG
  let configuration = "debug"
#elseif RELEASE
  let configuration = "release"
#endif
5
blackjacx

à stocker

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()
2
Hardik Thakkar