secondary property update not sticking after animation
Asked Answered
N

2

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). :/

Neophyte answered 20/7, 2016 at 23:34 Comment(0)
N
0

percentScanned needed to be set as a @dynamic variable so that Core Animation implements the accessors for you, per https://mcmap.net/q/460408/-animating-a-custom-property-of-calayer-subclass

Neophyte answered 30/8, 2016 at 5:9 Comment(0)
S
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.

Substation answered 10/8, 2016 at 8:50 Comment(9)
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....Neophyte
But the animation is running, add a conditional breakpoint on the value being set and check when it's set to zeroSubstation
Apologies if I fail on following through; baby just came a couple weeks early.Neophyte
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.Neophyte
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...Neophyte
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 thereSubstation
Hmm. Removed transaction, removed "to" value, ... is simplified, but is still jumping to "0" at the end. :/Neophyte
Not sure why then :-(Substation
Created 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.Neophyte
N
0

percentScanned needed to be set as a @dynamic variable so that Core Animation implements the accessors for you, per https://mcmap.net/q/460408/-animating-a-custom-property-of-calayer-subclass

Neophyte answered 30/8, 2016 at 5:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.