2010-02-19 14 views
16

Próbuję nieco lepiej zrozumieć mechanizm kodowania wartości klucza (KVC) firmy Cocoa. Przeczytałem numer Key-Value Programming Guide firmy Apple, ale nadal jestem nieco zdezorientowany tym, jak niektóre metody KVC szukają kluczy. W szczególności mutableArrayValueForKey:.Jaki jest wzór wyszukiwania KVC dla mutableArrayValueForKey?

Poniżej wyjaśnię, jak rozumiem, że "gettery" KVC działają. Następnie przejdę do mojego pytania dotyczącego mutableArrayValueForKey.


Istnieje siedem różnych "Getter" Metody KVC:

- (id)valueForKey:(NSString *)key; 
- (id)valueForKeyPath:(NSString *)keyPath; 
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys; 
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key; 
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath; 
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key; 
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath; 

Podczas poszukiwania Wartość wewnątrz posesji (o nazwie MyKey), docs Apple członkowskiego, które valueForKey: wyszukiwań jak ten :

  1. Próbuje -getMyKey, -myKey i -isMyKey (w tej kolejności) wewnątrz odbiornika
  2. Jeśli nie znaleziono, to Próby te zamawiane, do wielu getters (NSArray):

    // Required: 
    - (NSUInteger)countOfMyKey; 
    
    // Requires At Least One: 
    - (id)objectInMyKeyAtIndex:(NSUInteger)index; 
    - (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes; 
    
    // Optional (improves performance): 
    - (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange; 
    
  3. Następnie próbuje te nieuporządkowane, do wielu pobierające (NSSet) :

    - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey; 
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject; 
    
  4. Następnie próbuje uzyskać dostęp do zmiennych instancji bezpośrednio, zakładając YES jest zwracany przez accessInstanceVariablesDirectly, w następującej kolejności: _myKey, _isMyKey, myKey, isMyKey.

  5. Na koniec poddaje się i wywołuje metodę klasy przyjmującej: - (id)valueForUndefinedKey:(NSString *)key. Zwykle tutaj powstaje błąd.


Moje pytanie brzmi, jaki jest wzór porządek poszukiwanie mutableArrayValueForKey :?

Apple's docs state this:

Accessor Szukaj Wzór dla zamówionych Kolekcje

Wzór domyślną wyszukiwarką dla mutableArrayValueForKey: jest jako następująco:

klasy odbiornika jest poszukiwany przez pary metod, których nazwy pasują do wzorców -insertObject: inAtIndex: i -removeObjectFromAtIndex: (odpowiadające NSMutableArray prymitywnych sposobów insertObject: atIndex a removeObjectAtIndex:), lub metody dopasowania wzorca -WSTAW: atIndexes a -removeAtIndexes: (odpowiadające NSMutableArrayinsertObjects: atIndexes : i removeObjectsAtIndexes: methods). Jeżeli co najmniej jeden sposób wkładania i co najmniej jeden sposób usuwania można znaleźć każda wiadomość NSMutableArray wysyłane do obiektu proxy kolekcja wynik jako kombinacja -insertObject: inAtIndex :, -removeObjectFromAtIndex :, -WSTAW: atIndexes: i -removeAtIndexes: wiadomości wysyłane do oryginalnego odbiorcy mutableArrayValueForKey :. ... itd ...

To nie ma dla mnie sensu, ponieważ omawia metody "setera". mutableArrayValueForKey: zwraca wartość NSMutableArray. Wszystkie wymienione powyżej metody zwróciły nieważne i są używane do edycji obiektu NSMutableArray, ale go nie otrzymują. Przykład:

- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index; 
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index; 

Jakieś pojęcie, co Apple próbuje powiedzieć w swoich dokumentach, a może to błąd?

Moja teoria jest taka, że ​​mutableArrayValueForKey: prawdopodobnie podąża podobną ścieżką, co valueForKey: podczas wyszukiwania w celu uzyskania wartości KVC. Po prostu nie jestem pewien, jaka to naprawdę jest ścieżka.

Dzięki za pomoc, jaką możesz zaoferować! :)

Odpowiedz

21

NSMutableArray wrócisz z wywołaniem mutableArrayValueForKey: jest rzeczywiście prywatny podklasa NSMutableArray który zastępuje normalne metody macierzy takie jak -count, -objectAtIndex:, -insertObject:atIndex: itp i wywołuje odpowiednie metody KVC na obiekcie tablica została pobrana z . Zasadniczo działa jako pośrednik do manipulowania relacją do obiektu w bardzo wielu i nie jest to coś, o co musisz się martwić w związku z tworzeniem lub zwracaniem siebie. Szybki przykład użycia:

Playlist* aPlaylist; 
Track* aTrack; 
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"]; 
[mutableTracks insertObject:aTrack atIndex:0]; 

Ten fragment kodu dodaje ścieżkę do początku listy odtwarzania. Jeśli klasa Playlist implementuje metody KVC dla relacji "ślady", wywołanie metody w tablicy zmiennych spowoduje wywołanie odpowiedniej metody dla obiektu bazowego. Tak więc w tym przykładzie, gdy wywołasz insertObject:atIndex: w tablicy, tablica wywoła z kolei obiekt insertObjectInTracks:atIndex: na obiekcie listy odtwarzania, a ścieżka zostanie dodana do listy ścieżek listy odtwarzania.

Teraz, w tym przykładzie, można oczywiście po prostu zadzwonić pod numer insertObjectInTracks:atIndex:, ale istnieje kilka korzyści, które można uzyskać zamiast używania mutableArrayValueForKey:.

  • Opakowanie macierzy ukrywa szczegóły implementacji podstawowych metod KVC. Wdrożenie całej listy metod nie jest ściśle wymagane, aby była zgodna z KVC. Klasa Playlist może po prostu zaimplementować -tracks i -setTracks:, a powyższy kod nadal będzie działał. W tym przypadku zamiast wywoływania insertObjectInTracks:atIndex:, zmienna tablica proxy utworzy nową tablicę z obiektem wstawionym na początku, a następnie po prostu wywoła setTracks: na obiekcie Playlist. Jest to oczywiście mniej wydajne, dlatego zalecana jest zazwyczaj implementacja pełnej listy metod KVC.
  • W przypadku, gdy zamiast ciągłego ciągu dla klucza, zamiast tego masz zmienną, używając mutableArrayValueForKey: pozwala manipulować relacją bez konieczności znajomości dokładnych nazw metod, które musisz wywołać. Tak długo, jak obiekt jest zgodny z KVC dla klucza, którego używasz, wszystko "działa".
  • Pozwala również na użycie dowolnej metody implementowanej przez samą NSMutableArray, więc możesz na przykład użyć metod, które przeszukują tablicę w poszukiwaniu obiektów, sortują tablicę itd. Bez konieczności przepisywania specjalnych wersji, aby poradzić sobie z materiałem KVC.
+0

Dzięki Brian, to było bardzo pomocne. :) –

+1

"Ten fragment kodu dodaje ścieżkę do początku playlisty", myślę, że dodaje utwór na początku utworów, a nie na playlistę? –

+0

jest istotne, aby powiedzieć, że to podejście jest istotne, gdy używane są wiązania. W powyższym przykładzie, jeśli Playlist jest NSArrayController związany z tablicą śladów i mamy NSTableView związany z tym kontrolerem, to aby zmiany w ścieżkach mogły być odzwierciedlone w tabeli za pośrednictwem kontrolera tablicowego, musimy uzyskać ścieżki od zmiennej array proxy, a następnie dodaj/usuń obiekty na tej ścieżce: infact te operacje będą odzwierciedlały polecenia KVC, które wyzwalą mechanizm bindowania. – viggio24