Bezpośredni dostęp do zagnieżdżonych wartości słownika w Objective-C

Czy istnieje sposób na bezpośredni dostęp do wewnętrznej tablicy zewnętrznej tablicy an w Objective-C? Na przykład wywołanie zewnętrznego źródła danych zwraca następujący obiekt:

{
bio = "this is the profile.bio data";
"first_name" = John;
"last_name" = Doe;
location =     {
    name = "Any Town, Any State";
};
metadata =    {
    pictures =    {
        picture = "https://picture.mysite.com/picture.jpeg";
    }
}
}

Chcę mieć dostęp np. do location.name albo metadanych.zdjęcia.dane obrazkowe. Notacja kropkowa nie wydaje się jednak działać. Na przykład:

_gfbLocation = [result objectForKey:@"location.name"];
_gfbPicture = [result objectForKey:@"metadata.pictures.picture"];

Jedyny sposób, w jaki mogłem uzyskać dostęp do tych danych, to ustawienie zawartości tablic wewnętrznych na obiekty. Myśli?

Author: Simon Whitaker, 2010-11-30

3 answers

Dla zagnieżdżonych kluczy, takich jak ten, można użyć ścieżki . Klawiatura to po prostu seria klawiszy połączonych kropkami. Można ich używać do pobierania zagnieżdżonych wartości z obiektów obsługujących kodowanie wartości klucza - w tym obiektów NSDictionary, takich jak Twój. Więc w Twoim przypadku powinno to działać:

[result valueForKeyPath:@"location.name"];

Aby uzyskać więcej informacji na temat kodowania klucz-wartość, zobacz Przewodnik Apple key-Value Coding Programming Guide .

Zobacz także to powiązane pytanie o StackOverflow .

 57
Author: Simon Whitaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:21

Korzystając z poprawnej odpowiedzi Simona Whitakera, udało mi się zbudować hierarchię stałych poprzez osadzenie słownika w słowniku w słowniku. Poniżej znajduje się przykładowy kod źródłowy, zmodyfikowany z mojego prawdziwego kodu źródłowego.

To jest realne rozwiązanie problemu. W moim konkretnym przypadku celem było zorganizowanie ciągów identyfikujących produkty dostępne za pośrednictwem StoreKit do zakupu w aplikacji w sklepie Apple App Store dla iOS. Wyobraź sobie, że nasza aplikacja prezentuje treści z pary książek, jednej o kotach, inne psy. Ponadto nasza aplikacja sprzedaje skróconą wersję treści, jak również nieskrępowaną. Aktualizacja z skróconego do nieskorygowanego oznacza trzeci produkt, "upgrade". Każda para książek może zostać przetłumaczona, w tym przypadku na angielski i włoski.

Patrząc na struny, które próbuję śledzić, możesz pomyśleć: "dlaczego ten facet nie używa samych strun, zamiast przechodzić przez ten nonsens KVC?". Zwróć uwagę na 2. stringi, angielski > koty > Unabridged. The string ends z dołączonym podkreśleniem. Dzieje się tak dlatego, że kiedy używałem iTunesConnect do tworzenia produktów zakupu w aplikacji, przypadkowo utworzyłem ten przedmiot jako "materiały eksploatacyjne" zamiast "Nie zużywalne". Apple nie zezwala na zmianę identyfikatora, nawet jeśli usuniesz wspomniany produkt. Tak więc oryginalny ciąg znaków nie mógł być użyty; alternatywnie dodałem podkreślenie jako obejście. Chodzi o to, że te ciągi są dowolne i niechlujne.

Inną podobną potrzebę takiego podejścia byłoby, gdyby te wartości ciągu może się od czasu do czasu zmieniać w czasie kompilacji, więc nie chcesz kopiować-wklejać do więcej niż jednego miejsca w kodzie źródłowym. Hierarchia stałych, innymi słowy.

Wewnątrz Xcode, chcę lepszy sposób odwoływania się do tych identyfikatorów produktów.

// Using new literals syntax in later versions of Xcode 4 (& 5) to declare and populate a dictionary nested in a dictionary also in a dictionary.
NSDictionary *productIdentifiersHierarchy = @{
                                              @"en" : @{
                                                      @"cats" : @{
                                                              @"abridged" : @"com.example.My_App.cats_abridged_en",
                                                              @"unabridged" : @"com.example.My_App.cats_unabridged_en_",
                                                              @"upgrade" : @"com.example.My_App.cats_upgrade_en"
                                                              },
                                                      @"dogs" :  @{
                                                              @"abridged" : @"com.example.My_App.dogs_abridged_en",
                                                              @"unabridged" : @"com.example.My_App.dogs_unabridged_en",
                                                              @"upgrade" : @"com.example.My_App.dogs_upgrade_en"
                                                              }
                                                      },
                                              @"it" : @{
                                                      @"cats" : @{
                                                              @"abridged" : @"com.example.My_App.cats_abridged_it",
                                                              @"unabridged" : @"com.example.My_App.cats_unabridged_it",
                                                              @"upgrade" : @"com.example.My_App.cats_upgrade_it"
                                                              },
                                                      @"dogs" :  @{
                                                              @"abridged" : @"com.example.My_App.dogs_abridged_it",
                                                              @"unabridged" : @"com.example.My_App.dogs_unabridged_it",
                                                              @"upgrade" : @"com.example.My_App.dogs_upgrade_it"
                                                              }
                                                      }
                                              };

Oto jak uzyskać dostęp do tych potrójnie zagnieżdżonych słowników.

// Use KVC (Key-Value Coding) as a convenient way to access the nested dictionary structure.
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.upgrade"],

NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.upgrade"],

NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.upgrade"],

NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.abridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.unabridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.upgrade"] );
 1
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-16 06:04:48
gfbPicture = [[[result objectForKey:@"metadata"] objectForKey:@"pictures"] objectForKey:@"picture"];
 0
Author: Matt Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-30 19:42:44