【iOS】自定义CALayer可能会出现没有动画过程但有动画结果的解析

按照计划是要做成这样的动画
这里写图片描述
可是结果变成了这样
这里写图片描述
(有时候最重要的不是结果而是过程,日常鸡汤)

结果没有问题说明delegate中- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;成功执行,故此文不做讨论

让我们看看自定义的CALAyer的代码

- (void)drawInContext:(CGContextRef)ctx {
//    self.lineWidth = 2;
    self.endAngle = 360;
    self.startAngle = 0;

    CGFloat sColorR = 94.0 / 256;
    CGFloat sColorG = 127.0 / 256;
    CGFloat sColorB = 242.0 / 256;
    CGFloat sColorA = 1;

    CGFloat radius = self.bounds.size.width / 2;
    CGFloat lineWidth = self.lineWidth;
    UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius - lineWidth / 2 startAngle:self.startAngle * M_PI * 2 / 360 endAngle:(self.endAngle == 0 ? 360 : self.endAngle) / 360 * M_PI * 2 * self.progress clockwise:YES];

    CGContextSetRGBStrokeColor(ctx, sColorR, sColorG, sColorB, sColorA);//笔颜色
    CGContextSetLineWidth(ctx, lineWidth);//线条宽度
    CGContextAddPath(ctx, path.CGPath);
    CGContextStrokePath(ctx);
}
- (instancetype)initWithLayer:(CircleProgressLayer *)layer {
    if (self = [super initWithLayer:layer]) {
        self.progress = layer.progress;

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

看来貌似是self.lineWidth没有赋值的原因,那么这个时候我又分为两种情况来进行试着解决。

  • drawInContext()方法内对其赋值,结果有效。
  • CALayer外对其赋值,居然还是回到了之前错误的状况。

从方法的复用性来讲我们肯定提倡使用第二种方式对属性进行修改,所以在drawInContext()中我打了断点,如同设想中的一样,每进行一次动画的时候,该方法会调用几次,同时每次调用的时候我还发现了一件极其有趣的事情。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
可以看到,每次调用方法的时候,self的指针都发现了不同程度的变化,而在使用CALayer的时候我肯定不会做重复init这么傻的事情的。所以可以推测出,在执行动画的过程中,iOS会一直在init新的CALayer,以期达到“动”画的效果直到动画结束。
所以可以推测出,没有动画过程的问题是在于“动”的过程中有些固定参数没有传达到新的init的CALayer上。那么我们应该要怎么传达原有CALayer的参数呢?

- (instancetype)initWithLayer:(CircleProgressLayer *)layer {
    if (self = [super initWithLayer:layer]) {
        self.progress = layer.progress;
        self.lineWidth = layer.lineWidth;
    }
    return self;
}

也就是晚上之前的init方法就可以让原layer的参数一份不落地传递过来了,以上。

posted @ 2017-12-05 13:58  MrYu4  阅读(31)  评论(0编辑  收藏  举报