Анимация пользовательского свойства подкласса CALayer

У меня есть подкласс CALayer, MyLayer, который имеет свойство NSInteger, называемое myInt. Я бы очень хотел оживить это свойство через CABasicAnimation, но, похоже, CABasicAnimation работает только с так называемыми "анимативными" свойствами (границами, позицией и т.д.). Есть ли что-то, что я могу переопределить, чтобы сделать мое пользовательское свойство myInt анимированным?

Ответ 1

Да, это возможно (только в последних версиях Core Animation, хотя, я считаю, то есть iPhone 3.0+ и OS X 10.6 +).

  • Сделайте вашу динамическую структуру так, чтобы CA реализовал для вас аксессоры:

    @dynamic myInt;
    
  • Сообщите слою, что изменения свойства требуют перерисовки:

    + (BOOL)needsDisplayForKey:(NSString*)key {
        if ([key isEqualToString:@"myInt"]) {
            return YES;
        } else {
            return [super needsDisplayForKey:key];
        }
    }
    
  • Используйте значение myInt в вашем методе drawInContext:. Теперь, когда вы анималируете myInt, Core Animation будет интерполировать значения для каждого шага анимации и повторно просить слой рисовать сам.

  • Если вы также хотите включить неявные анимации для этого свойства, также переопределите actionForKey:.

Ответ 2

Существует способ сохранить iVars ваших пользовательских подклассов CALayer. Вы переопределяете initWithLayer:, метод, который вызывается для создания копии пользовательских слоев. Например, если у вас есть слой, в котором вы хотите создать настраиваемое свойство под названием "угол", вы можете использовать следующий код:

@implementation AngledLayer
@synthesize angle = _angle

// Tell Core Animation that this key should be animated
+ (BOOL) needsDisplayForKey:(NSString *)key
{
    if ([key isEqualToString:@"angle"]) return YES;
    return [super needsDisplayForKey:key];
}


// Make sure that, when the layer is copied, so is the custom ivar
- (id) initWithLayer:(id)layer
{
    self = [super initWithLayer:layer];
    if (self) {
        AngledLayer *angledVersion = (AngledLayer *)layer;
        self.angle = angledVersion.angle;
    }
    return self;
}

И помоги своему дяде! Обратите внимание: вы не можете использовать этот объект с неявной анимацией, для которой вам также нужно будет переопределить метод actionForKey:.