Как именно подклассировать CALayer и использовать настраиваемое свойство?
Я пытаюсь создать подкласс CALayer
с пользовательским свойством index
, который можно как анимировать, так и напрямую изменить, чтобы отобразить другое изображение на основе индекса.
В заголовке я заявил:
@property NSUInteger index;
В реализации я перегрузил needDisplayForKey
:
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:@"index"])
return YES;
else
return [super needsDisplayForKey:key];
}
Теперь, в методе display
, я хочу отобразить изображение на основе индекса. Однако во время анимации значение self.index
никогда не изменяется, поэтому я должен запрашивать значение уровня представления, в отличие от примера Предоставление содержимого CALayer по подклассу:
- (void)display
{
NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index];
self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage];
}
Проблема в том, что если я это сделаю, я не могу установить значение index
непосредственно вне анимации, потому что он изменит только слой модели, а метод display
явно запросит уровень представления.
Если я добавлю метод инициализации, который копирует значение index
, он работает:
- (id)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self) {
if ([layer isKindOfClass:[CustomLayer class]])
self.index = [(CustomLayer *)layer index];
}
return self;
}
Однако после или до анимации всегда есть 1 сбой изображения, потому что представление или значение модели не совпадают (в зависимости от того, установлен ли значение index
на целевое значение или нет).
- Удивительно, но похоже, что метод
drawInContext:
всегда имеет
правильное значение для [self index]
, но это не тот метод, который я хочу использовать, поскольку я просто установил свойство content
с изображением.
- Я получаю различное поведение в зависимости от того, как я реализую свойство
index
. Если я использую @dynamic index
(который работает, хотя в документации не говорится, что пользовательские свойства getters/seters будут динамически реализованы), display
вызывается каждый раз, когда изменяется значение index
. Если я использую @synthesize
или реализую сеттер, display
не вызывается, поэтому мне также нужно будет изменить content
в настройщике.
- Должен ли я использовать переменную экземпляра? Должен ли я использовать динамическую реализацию? Или я должен использовать
setValue:forKey:
вместо этого?
Как вы можете видеть, я немного смущен тем, как получить результат, который я хочу, и как правильно реализовать подкласс CALayer с настраиваемым свойством. Любая помощь и объяснения будут оценены!
Ответы
Ответ 1
В Интернете есть отличный учебник, в котором объясняется, как создать пользовательский подкласс CALayer с анимированными свойствами. У меня еще не было возможности попробовать его, но я добавил его в закладки. Вот ссылка:
Анимация кусочков пирога с использованием пользовательского CALayer
Похоже, основные трюки:
Используйте @dynamic, а не @synthesize для анимационных свойств вашего пользовательского CALayer.
Переопределить actionForKey:, initWithLayer:, and needsDisplayForKey:, и возможно drawInContext: