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ć?

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];

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)")
}

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"];

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

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()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.