Komunikacja i utrwalanie danych między aplikacjami za pomocą grup aplikacji

85

iOS 8 ujawnił wczoraj nowe API dotyczące grup aplikacji. Udostępnianie danych i komunikowanie się między aplikacjami było trochę bałaganiarskie i uważam, że właśnie to mają poprawić grupy aplikacji.

W mojej aplikacji włączyłem grupy aplikacji i dodałem nową grupę, ale po prostu nie mogę znaleźć żadnej dokumentacji, jak z niej korzystać. Dokumentacja i odniesienia do API określają jedynie, jak dodać grupę.

Co tak naprawdę mają robić grupy aplikacji? Czy jest gdzieś dokumentacja, jak go używać?

streem
źródło

Odpowiedzi:

81

Kolejną zaletą grup aplikacji jest możliwość współużytkowania NSUserDefaultsbazy danych. Działa to również w przypadku rozszerzeń aplikacji (widżety centrum powiadomień, niestandardowe klawiatury itp.).

Zainicjuj swój NSUserDefaultsobiekt w ten sposób we wszystkich aplikacjach w grupie aplikacji, a będą one udostępniać bazę danych:

Cel C:

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

Szybki:

NSUserDefaults(suiteName: "<group identifier>")

Należy pamiętać, że wszystko z [NSUserDefaults standardUserDefaults]bazy danych dla każdej aplikacji nie zostanie przeniesione do tej bazy danych.

Dokumentacja daje poprawną przykładem, jak również (jako Beta 3).

I nie zapomnij zsynchronizować bazy danych:

[yourDefaults synchronize];
Święty Mikołaj
źródło
2
Działa tylko na symulatorze (XCode 6 beta 5, iOS 8 beta 5)
iOS Dev
8
UWAGA: Jeśli używasz tego z rozszerzeniem iOS 8 (np. Klawiatura), musisz upewnić się, że Twoje rozszerzenie ma RequestsOpenAccess = YES w swoim pliku Info.plist.
Kiran Panesar
1
Zrobiłem RequestsOpenAccess = YES i postępuj zgodnie z instrukcją, ale nadal nie działa dla mnie na urządzeniu i działa dobrze na emulatorze, czy coś specyficznego dla urządzenia?
MAC,
Ten sam problem ze mną, mam zintegrowane rozszerzenie udostępniania w mojej aplikacji, działa na symulatorze, ale nie działa na prawdziwym urządzeniu, dodałem RequestOpenAccess = TAK, ale to nie działa, moje pytanie to stackoverflow.com/questions/30489894/ …
Ravi Ojha
3
@MikeRichards nie jestem pewien, ale jeśli dobrze pamiętam, grupy aplikacji są poprzedzone identyfikatorem zespołu
Święty Mikołaj
74

Udostępnianie danych NSUserDefaults między wieloma aplikacjami

Aby mieć wspólne ustawienia domyślne między aplikacją a rozszerzeniem lub między 2 aplikacjami, musisz dodać grupę aplikacji w ustawieniach, wykonując następujące czynności:

  1. W Nawigatorze projektu kliknij plik * .xcodeproj (powinien znajdować się na górze).
  2. Po prawej stronie Nawigatora projektu poszukaj opcji Projekt i Cele. Pod celami kliknij swój główny cel (powinno być pierwszą rzeczą w obszarze Cele).
  3. U góry kliknij kartę Możliwości.
  4. W sekcji Grupy aplikacji kliknij przełącznik po prawej stronie, aby WŁĄCZYĆ Grupy aplikacji.
  5. Kliknij przycisk + i dodaj grupę aplikacji o nazwie group.com.company.myApp .
  6. Przejdź w to samo miejsce w innych aplikacjach, a ta grupa powinna być teraz dostępna do wyboru. Włącz tę grupę dla każdej aplikacji, która będzie używać tych udostępnionych danych.

Uwaga: jeśli przejdziesz do portalu Apple Developer Portal (witryna firmy Apple, która zawiera wszystkie Twoje certyfikaty, identyfikatory, urządzenia i profile obsługi administracyjnej) i wybierzesz Identyfikatory> Grupy aplikacji, powinieneś zobaczyć tę nową grupę aplikacji.

Aby przechowywać dane:

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

Aby odzyskać dane:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
  print("User Id: \(testUserId)")
}
TenaciousJay
źródło
2
Dzięki! Zajęło trochę czasu przeszukiwania dokumentacji, aby dowiedzieć się, jak to zrobić i pomyślałem, że inni mogą docenić podjęte przeze mnie kroki.
TenaciousJay,
Dzięki za szczegółowy opis ...! Czy musimy utworzyć jakikolwiek certyfikat z portalu Apple Developer Portal (witryny Apple, która pokazuje wszystkie Twoje certyfikaty, identyfikatory, urządzenia i profile obsługi administracyjnej), aby włączyć tę grupę? tak samo jak powiadomienia push.?
Arbaz Shaikh
Gdy wykonasz krok 5, powinieneś dodać grupę aplikacji do portalu dla deweloperów firmy Apple, nie musisz przechodzić bezpośrednio do portalu dla programistów, aby ją dodać. Po wykonaniu kroku 5 możesz przejść do portalu i przekonać się, że powinien go on dla Ciebie utworzyć.
TenaciousJay,
@TenaciousJay Znakomita odpowiedź. Po prostu chcę dodać Jeśli chcesz uruchomić aplikację z aplikacji func (aplikacja: UIApplication, openURL url: NSURL, opcje: [String: AnyObject]) -> Bool
Taimur Ajmal
świetna odpowiedź. dzięki @TenaciousJay. Próbuję pobrać zmienną i jej wartość z AppB do AppA, jak mam to zrobić? Na przykład, jeśli „riderCancelledRequest = true” w AppB, jak mógłbym to pobrać w AppA?
LizG
37

Grupy aplikacji, zgodnie z moją interpretacją istniejącej dokumentacji, są przeznaczone przede wszystkim na rozszerzenia, a dokładniej na widżety. Widżety to własny pakiet aplikacji, który współistnieje z Twoją aplikacją. Ponieważ są one oddzielną aplikacją i dlatego mają własną piaskownicę, do udostępniania plików będziesz musiał używać grup aplikacji.

Po pewnym grepowaniu nagłówka wydaje mi się, że API jest potrzebne, ale w rzeczywistości zostało wprowadzone jako część iOS 7.

NSFileManagerzawiera metodę, dzięki containerURLForSecurityApplicationGroupIdentifier:której możesz przekazać identyfikator utworzony podczas włączania grup aplikacji dla swoich aplikacji:

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];
Wayne Hartman
źródło
Dzięki, myślę, że masz rację co do rozszerzalności. Trochę bardziej wątpię w tę metodę iOS 7, wydaje mi się dość statyczna, iOS 8 wprowadził rzeczywiste interakcje i komunikację między aplikacjami.
streem
@Justafinger Ta metoda iOS 7 służy tylko do tworzenia adresu URL do zapisywania i odczytywania danych między udostępnionymi aplikacjami. Ta konkretna metoda jest naprawdę przydatna (z tego, co widzę do tej pory) w przypadku widżetów, ale nie innych rozszerzeń.
Wayne Hartman
Cóż, uważam, że Apple chciał ułatwić to w iOS 8 bez konieczności programowego tworzenia kontenera i udostępniania niestandardowych plików. Dokumentacja stwierdza, że ​​powinno być możliwe udostępnianie danych przy użyciu NSUserDefault. Chyba czegoś mi brakuje, bo to nie działa dla mnie.
streem
@Justafinger Ja też nie mogłem dostać się NSUserDefaultsdo pracy. Kredytuję do błędu Beta 1.
Wayne Hartman
@WayneHartman Istnieje obejście dla NSUserDefaultsbazy danych. Zobacz moją odpowiedź.
Święty Mikołaj
6

Jedna ważna pułapka, w którą dziś wpadłem, jest następująca:

W wielu projektach widziałem jeden cel aplikacji iz różnymi identyfikatorami pakietów ustawionymi dla każdej konfiguracji tego celu. Tutaj robi się bałagan. Programiści zamierzali stworzyć aplikację do debugowania dla konfiguracji debugowania i aplikację produkcyjną dla celu wydania.

Jeśli to zrobisz, obie aplikacje będą współdzielić te same NSUserDefaults, gdy zostaną skonfigurowane w ten sposób

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

Powoduje to problemy w wielu miejscach:

  1. Wyobraź sobie, że ustawiłeś TAK dla klawisza, gdy specjalny ekran wprowadzający do aplikacji został pokazany użytkownikowi. Druga aplikacja również odczyta teraz TAK i nie pokaże wprowadzenia.
  2. Tak, niektóre aplikacje przechowują również tokeny OAuth w domyślnych ustawieniach użytkownika. W każdym razie ... W zależności od implementacji aplikacja rozpozna, że ​​istnieje token i zacznie pobierać dane przy użyciu niewłaściwego tokena. Jest duża szansa, że ​​zakończy się to niepowodzeniem z dziwnymi błędami.

Ogólnym rozwiązaniem tego problemu jest poprzedzenie kluczy domyślnych bieżącą, zbudowaną konfiguracją. Konfigurację można łatwo wykryć w czasie wykonywania, ustawiając różne identyfikatory pakietów dla swoich konfiguracji. Następnie po prostu przeczytaj identyfikator pakietu z NSBundle.mainBundle(). Jeśli masz te same identyfikatory pakietów, musisz ustawić różne makra preprocesora, takie jak

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

W Swift będzie wyglądać prawie tak samo:

#if DEBUG
  let configuration = "debug"
#elseif RELEASE
  let configuration = "release"
#endif
blackjacx
źródło
8
Twoje problemy istnieją, ponieważ mieszasz wszystkie swoje dane we współdzielonych plikach UserDefaults. Należy użyć NSUserDefaults.standardUserDefaults()dla danych, które nie powinny być udostępniane.
Daniel
2

Przechować

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()
Hardik Thakkar
źródło