Comunicazione e persistenza dei dati tra le app con i gruppi di app


85

iOS 8 ha rivelato ieri una nuova API relativa ai gruppi di app. Prima era un po 'complicato condividere dati e comunicare tra app e credo che sia esattamente ciò che App Groups dovrebbe correggere.

Nella mia app ho abilitato App Groups e aggiunto un nuovo gruppo, ma non riesco a trovare alcuna documentazione su come usarlo. La documentazione e i riferimenti API indicano solo come aggiungere un gruppo.

Quindi cosa intende veramente fare App Groups? C'è qualche documentazione da qualche parte su come usarlo?

Risposte:


81

Un altro vantaggio dei gruppi di app è la possibilità di condividere un NSUserDefaultsdatabase. Funziona anche per le estensioni app (widget del centro notifiche, tastiere personalizzate, ecc.).

Inizializza il tuo NSUserDefaultsoggetto in questo modo in tutte le applicazioni nel gruppo di app e condivideranno il database:

Obiettivo-C:

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

Swift:

NSUserDefaults(suiteName: "<group identifier>")

Tieni presente che tutto dal [NSUserDefaults standardUserDefaults]database per ciascuna applicazione non verrà trasferito in questo database.

La documentazione fornisce anche un esempio corretto (A partire dalla Beta 3).

E non dimenticare di sincronizzare il database:

[yourDefaults synchronize];

2
Funziona solo su simulatore (XCode 6 beta 5, iOS 8 beta 5)
iOS Dev

8
NOTA: se lo stai utilizzando con un'estensione iOS 8 (ad esempio una tastiera), dovrai assicurarti che l'estensione abbia RequestsOpenAccess = YES nel suo file Info.plist.
Kiran Panesar

1
Ho fatto RequestsOpenAccess = YES e ho seguito le istruzioni ma non funziona per me sul dispositivo e funziona bene sull'emulatore, qualcosa di specifico per il dispositivo?
MAC

Lo stesso problema con me, ho integrato l'estensione di condivisione nella mia app, funziona sul simulatore, ma non funziona sul dispositivo reale, ho aggiunto RequestOpenAccess = YES ma non funziona, la mia domanda è stackoverflow.com/questions/30489894/ ...
Ravi Ojha

3
@MikeRichards non ne sono sicuro, ma se ricordo bene i gruppi di app sono preceduti da un ID squadra
Babbo Natale

74

Condivisione dei dati NSUserDefaults tra più app

Per avere impostazioni predefinite condivise tra un'app e un'estensione o tra 2 app, devi aggiungere un gruppo di app nelle tue impostazioni utilizzando i seguenti passaggi:

  1. Nel Navigatore progetto fare clic sul file * .xcodeproj (dovrebbe essere in alto).
  2. A destra del Navigatore progetto cerca Progetto e Obiettivi. Sotto Target, fai clic sul tuo obiettivo principale (dovrebbe essere la prima cosa sotto Target).
  3. Verso l'alto, fai clic sulla scheda Capacità.
  4. Nella sezione Gruppi di app fare clic sull'interruttore a destra per attivare i gruppi di app.
  5. Fare clic sul pulsante + e aggiungere un gruppo di app denominato group.com.company.myApp .
  6. Vai nella stessa posizione nelle altre tue app e questo gruppo dovrebbe ora essere disponibile per la selezione. Attiva questo gruppo per ogni app che utilizzerà questi dati condivisi.

Nota: se vai al Portale per sviluppatori Apple (il sito web di Apple che mostra tutti i tuoi certificati, identificatori, dispositivi e profili di provisioning) e vai su Identificatori> Gruppi di app dovresti vedere questo nuovo gruppo di app.

Per memorizzare i dati:

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

Per recuperare i dati:

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

2
Grazie! Ci è voluto un po 'di ricerca nella documentazione per capire come farlo e ho pensato che altri avrebbero potuto apprezzare i passaggi che ho intrapreso.
TenaciousJay

Grazie per la descrizione dettagliata ...! dobbiamo creare un certificato dal Portale per sviluppatori Apple (il sito Web di Apple che mostra tutti i tuoi certificati, identificatori, dispositivi e profili di provisioning) per abilitare questo gruppo? uguale alla notifica push.?
Arbaz Shaikh

Quando esegui il passaggio 5, dovrebbe aggiungere il gruppo di app al portale per sviluppatori Apple, non dovresti andare direttamente al portale per sviluppatori per aggiungerlo. Dopo aver eseguito il passaggio 5, puoi andare al portale e vedere che dovrebbe averlo creato per te.
TenaciousJay

@TenaciousJay Superb risposta. Voglio solo aggiungere Se vuoi avviare l'app dall'applicazione func (app: UIApplication, openURL url: NSURL, opzioni: [String: AnyObject]) -> Bool
Taimur Ajmal

Bella risposta. grazie @TenaciousJay. Sto cercando di recuperare una variabile e il suo valore da AppB in AppA, come potrei farlo? Ad esempio, se "riderCancelledRequest = true" in AppB, come lo recupererei in AppA?
LizG

37

I gruppi di applicazioni, secondo la mia interpretazione della documentazione esistente, sono principalmente destinati alle estensioni, più specificamente, ai widget. I widget sono il loro pacchetto di applicazioni che coesistono con la tua app. Poiché si tratta di un'applicazione separata e quindi hanno la propria sandbox, sarà necessario utilizzare i gruppi di app per condividere i file.

Dopo un po 'di grep di intestazione, penso di aver trovato l'API necessaria, ma in realtà è stata inserita come parte di iOS 7.

NSFileManagerha un metodo in containerURLForSecurityApplicationGroupIdentifier:cui puoi passare l'identificatore creato quando attivi i gruppi di app per le tue app:

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

Grazie, credo che tu abbia ragione sull'estensibilità. Sono un po 'più dubbioso su questo metodo iOS 7, mi sembra piuttosto statico, iOS 8 ha introdotto interazioni e comunicazioni reali tra le app.
streem

@Justafinger Questo metodo iOS 7 serve solo per creare un URL per scrivere e leggere dai dati tra le applicazioni condivise. Questo particolare metodo è veramente utile (da quello che vedo finora) solo per i widget, ma non per altre estensioni.
Wayne Hartman

Bene, credo che Apple volesse rendere tutto più semplice in iOS 8 senza dover creare un contenitore a livello di codice e condividere file personalizzati. La documentazione afferma che dovresti essere in grado di condividere i dati utilizzando NSUserDefault. Immagino che mi manchi qualcosa, perché per me non funziona.
streem

@ Justafinger nemmeno io sono riuscito a mettermi NSUserDefaultsal lavoro. Gesso fino al bug della Beta 1.
Wayne Hartman

@WayneHartman Esiste una soluzione alternativa per il NSUserDefaultsdatabase. Vedi la mia risposta.
Babbo Natale

6

Una trappola importante in cui mi sono imbattuto oggi è la seguente:

In molti progetti ho visto un'unica destinazione dell'app e con diversi identificatori di bundle impostati per ogni configurazione di quella destinazione. Qui le cose si complicano. L'obiettivo degli sviluppatori era creare un'app di debug per la configurazione di debug e un'app di produzione per l'obiettivo di rilascio.

Se lo fai, entrambe le app condivideranno gli stessi NSUserDefaults quando sono impostate in questo modo

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

Ciò causa problemi in molti punti:

  1. Immagina di impostare SÌ per una chiave quando una speciale schermata introduttiva dell'app è stata mostrata all'utente. Anche l'altra app ora leggerà SÌ e non mostrerà l'introduzione.
  2. Sì, alcune app memorizzano anche token oAuth nelle impostazioni predefinite dell'utente. Comunque ... A seconda dell'implementazione, l'app riconoscerà che c'è un token e inizierà a recuperare i dati usando il token sbagliato. È molto probabile che questo fallisca con strani errori.

La soluzione a questo problema in generale è anteporre alle chiavi di default la configurazione corrente creata. È possibile rilevare facilmente la configurazione in fase di esecuzione impostando diversi identificatori di bundle per le proprie configurazioni. Quindi leggi l'identificatore del bundle da NSBundle.mainBundle(). Se hai gli stessi identificatori di bundle, devi impostare diverse macro del preprocessore come

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

In Swift sembrerà quasi lo stesso:

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

8
I tuoi problemi esistono perché mischi tutti i tuoi dati in un UserDefaults condiviso. Dovresti usare NSUserDefaults.standardUserDefaults()per i dati che non dovrebbero essere condivisi.
Daniel,

2

Immagazzinare

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.