10

REPRO repository here: https://github.com/kaolin/38492498/tree/master


I have a @property int percentScanned.

I've set needsDisplayForKey:

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

My display method:

- (void)display {
    _percentTextLayer.string = [NSString stringWithFormat:@"%02d%%",[[self presentationLayer] percentScanned]];
}

My animation:

    [CATransaction begin];
    self.percentScanned = 99;
    _percentTextLayer.string=@"99%";
    [CATransaction setCompletionBlock:^{
        _percentTextLayer.string=@"99%";
        self.percentScanned = 99;
    }];
    {
        CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"percentScanned"];
        [a setFromValue:@0];
        [a setToValue:@99];
        [a setDuration:4.];
        [self addAnimation:a forKey:@"percentage"];
    }
    [CATransaction commit];

This all works fine, except at the end of the animation, my model layer string goes back to "00%". As you can see, I've thrown what feels like the kitchen sink at forcing it to stay at "99%" (outside of the "hack" of animation.removedOnCompletion = NO; and animation.fillMode = kCAFillModeForwards;—and actually, adding those doesn't help!).

I do have another animation on the same layer about 3/30 of a second later, fading the opacity.... But pushing that out, or deleting it, doesn't seem to make a difference.

I know how to do this for standard animated values, but I'm missing something for how to do this with a secondary/evaluated value like this....


EDITED TO ADD:

Somewhere along the way, adding animation.removedOnCompletion = NO; and animation.fillMode = kCAFillModeForwards; did actually start "working", but I'd like to not leak animations....

If I add a setter for percentScanned, it's not called with 0 at the end, but display is called with 0 at the end. It's kind of hard to trace the link between setPercentScanned being called and display being called...

I can hack my display to read as follows:

- (void)display {
    if ([[self presentationLayer] percentScanned] != 0) {
        _percentTextLayer.string = [NSString stringWithFormat:@"%02d%%",[[self presentationLayer] percentScanned]];
    }
}

Then it works for my particular use case, but that's still less than ideal....

And putting a breakpoint in the display method is fairly unhelpful (of course it's just happening inside display_if_needed). :/

Kaolin Fire
  • 2,521
  • 28
  • 43

2 Answers2

0

Basically, set the end value directly onto the layer and animate just the fromValue. So the value that the layer has is already correct at the end of the animation.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • I believe that's what I've done above. The same pattern works for all my properties except this one which is special because it's not a default-animated property.... – Kaolin Fire Aug 10 '16 at 17:31
  • 1
    But the animation is running, add a conditional breakpoint on the value being set and check when it's set to zero – Wain Aug 10 '16 at 18:46
  • Apologies if I fail on following through; baby just came a couple weeks early. – Kaolin Fire Aug 16 '16 at 03:58
  • Debugging, it looks like I'm just setting it once at the beginning to 0, then to 99 at the start of the animation, and then 0 to 99 in the animation. – Kaolin Fire Aug 16 '16 at 21:20
  • If I add a setter for percentScanned, it's never called with 0, but display is called with 0 at the end. It's kind of hard to trace the link between setPercentScanned being called and display being called... – Kaolin Fire Aug 16 '16 at 21:56
  • I'm not convinced you need the transaction, just set the final value and then animate from the start. you don't need to set the to value as it's already there – Wain Aug 16 '16 at 22:02
  • Hmm. Removed transaction, removed "to" value, ... is simplified, but is still jumping to "0" at the end. :/ – Kaolin Fire Aug 16 '16 at 22:20
  • Not sure why then :-( – Wain Aug 16 '16 at 22:22
  • Created https://github.com/kaolin/38492498/tree/master to show off the problem as minimally as I could.... :) Interestingly, I set the initial value to "HELLO WORLD", and it still resets to "00%" at the end. – Kaolin Fire Aug 16 '16 at 22:44
0

percentScanned needed to be set as a @dynamic variable so that Core Animation implements the accessors for you, per https://stackoverflow.com/a/2396461/856925

Community
  • 1
  • 1
Kaolin Fire
  • 2,521
  • 28
  • 43