2012-04-30 12 views
14

Próbuję utworzyć podklasę o wartości CALayer z niestandardową właściwością index, którą mogę zarówno animować, jak i zmieniać bezpośrednio, aby wyświetlić inny obraz na podstawie indeksu.Jak dokładnie podklasę CALayer i użyć niestandardowej właściwości?

W nagłówku, oświadczyłem:

@property NSUInteger index; 

W realizacji, ja overrode needDisplayForKey:

+ (BOOL)needsDisplayForKey:(NSString *)key 
{ 
    if ([key isEqualToString:@"index"]) 
     return YES; 
    else 
     return [super needsDisplayForKey:key]; 
} 

Teraz w sposobie display, chcę, aby wyświetlić obraz na podstawie indeksu . Jednak w trakcie animacji, wartość self.index nigdy się nie zmienia, więc muszę zapytać wartość warstwy prezentacji, w przeciwieństwie do przykładu na Providing CALayer Content by Subclassing:

- (void)display 
{ 
    NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index]; 
    self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage]; 
} 

Problem polega na tym, czy to zrobić, nie mogę Ustaw wartość index bezpośrednio poza animacją, ponieważ zmieni ona tylko warstwę modelu, a metoda display jawnie zapyta o warstwę prezentacji.

Jeśli dodać metodę inicjalizacji, która kopiuje wartość index, to działa:

- (id)initWithLayer:(id)layer 
{ 
    self = [super initWithLayer:layer]; 
    if (self) { 
     if ([layer isKindOfClass:[CustomLayer class]]) 
      self.index = [(CustomLayer *)layer index]; 
    } 
    return self; 
} 

Jednak po lub przed animacji, zawsze jest glitch 1 obraz, ponieważ prezentacja lub wartość modelu don dopasowanie (w zależności, czy ustawię index na wartość docelową, czy nie).

  • Co ciekawe, wydaje się, że metoda drawInContext: zawsze właściwą wartość dla [self index], ale to nie jest metoda chcę używać, ponieważ po prostu ustawić właściwość z obrazem content.
  • Dostaję różne zachowania w zależności od sposobu, w jaki implementuję właściwość index. Jeśli użyję @dynamic index (która działa, nawet jeśli w dokumentacji nie jest powiedziane, że niestandardowe właściwości pobierające/ustawiające będą dynamicznie zaimplementowane), display jest wywoływane za każdym razem, gdy zmieniana jest wartość index. Jeśli użyję @synthesize lub zaimplementuję ustawiacz, display nie zostanie wywołany, więc będę musiał zmienić także content w ustawiaczu.
  • Czy powinienem użyć zmiennej instancji? Czy powinienem użyć dynamicznej implementacji? Czy powinienem zamiast tego użyć setValue:forKey:?

Jak widać, jestem trochę zdezorientowany o tym, jak uzyskać wynik chcę i jak prawidłowo realizować podklasy CALayer z właściwości niestandardowej. Każda pomoc i objaśnienia zostaną docenione!

+2

„Dokumentacja nie mówi, że zwyczaj pozyskiwaniu nieruchomości/ustawiaczy będzie dynamicznie realizowane” - faktycznie, to * jest * udokumentowane 'CALayer.h':" CALayer implementuje standardowy protokół NSKeyValueCoding dla wszystkich właściwości Celu C zdefiniowanych przez klasę i jej podklasy, dynamicznie implementuje brakujące metody akcesorów dla właściwości zadeklarowanych przez podklasy. " Więc chcesz użyć '@ dynamic', jeśli chcesz, aby' + needsDisplayForKey: 'działało. –

+2

Świetne pytanie ... Te "podstawowe" pytania są niedostatecznie wyjaśnione w dokumentach i zbyt ezoteryczne dla wszystkich, ale najbardziej zaangażowanych w poradniki. "CALayer's to takie dziwne kule. Myślę, że Apple żałuje ich wdrożenia lub ma zbyt wiele konkurencyjnych technologii, aby zawracać sobie głowę dokumentowaniem swoich często tajemniczych zachowań. –

+3

Zgadzam się ... Podstawowa animacja jest trywialna w użyciu w podstawowych zadaniach, ale jeśli spróbujesz sięgnąć głębiej, stanie się ezoteryczna. Podobnie jak fakt, że warstwy mają taktowanie, oprócz czasu animacji. Lub tajemnicza właściwość 'contents', której typem jest' id', i która może zawierać buforowany 'CABackingStore'. Albo fakt, że "CATransition" dziedziczy po 'CAAnimation' działa w całkowicie nieprzejrzysty sposób ... Albo nawet relacja między blokami animacji" UIView "i animacją" CALayer "... – Guillaume

Odpowiedz

11

Istnieje doskonały samouczek w Internecie, który wyjaśnia, jak utworzyć niestandardową podklasę CALayer z właściwościami animacyjnymi. Nie miałem jeszcze okazji tego wypróbować, ale dodałem do zakładek. Oto link:

Animating Pie Slices Using a Custom CALayer

Wygląda główne sztuczki to:

Zastosowanie @dynamic nie @synthesize dla animatable właściwości niestandardowych CALayer.

Zastąp actionForKey :, initWithLayer :, a needsDisplayForKey :, a może drawInContext:

+0

Ten przykład wykorzystuje własną procedurę rysowania CoreGraphics w 'drawInContext:', które, jak powiedziałem, zawsze ma poprawną wartość animowanej właściwości. Jednak w metodzie "display" tylko przedstawiona wartość jest poprawna. Obejściem, którego ostatecznie użyłem do uzyskania pożądanego wyniku, jest zsyntetyzowanie właściwości i ręczne wywołanie 'setNeedsDisplay', gdy chcę wyświetlić zmianę właściwości poza animacją. – Guillaume

+0

Śmieszne .. Widziałem to i faktycznie wszystko działało ... na przykład na Maca. Postaram się opublikować klasy pracujące. –

Powiązane problemy