I have a NSImageView subclass which provides an audio waveform, and which 
creates a CALayer that animates a wiper that scrolls across the waveform as a 
track is playing using the ‘position’ params (to, from) along with the 
(remaining) track duration.

Until 10.13, I created the CALayer for the wiper in the imageView’s 
awakeFromNib method - as it would always have the same size and contents, and 
just needed to have its fromValue, toValue, and duration changed for either a 
new track, or a new start point in a track if the user clicked within the 
waveform.

This worked perfectly. To reposition the wiper, I’d remove the existing 
animation and add a new one to the wiper layer with updated from and duration 
values. (the ‘to’ value would always point to the end of the track).

But in 10.13 this no longer works. I find I have to create a new layer each 
time I need to reposition the wiper. Somehow it seems as though the layer 
property in my view (strong, nonatomic) no longer survives more than a single 
use.

All works normally now, by instantiating the CALayer each time I want to change 
on of its params, but I don’t understand what has changed in 10.13 to change 
the behavior. It took a bit of trial and error to find the fix.

I’m sure I was doing something wrong in the versions that ran perfectly under 
10.9 - 10.12, but I cannot find any documentation that explains why it would 
not work under 10.13, and it sort of bothers me that I now have to remove the 
existing CALayer (with the animation) and create a new CALayer just to 
reposition the wiper. 

Here’s the code that used to be in awakeFromNib: to create a layer that lasted 
for the entire app run:

        /*
        CGPoint zeroPt = CGPointMake(0,0);
        
        self.layer.anchorPoint = zeroPt;

        self.wiperLayer = [CALayer layer];
        [_wiperLayer setFrame:NSMakeRect(0, 0, 1, 61)]; // wiper is fixed 
width/height
        _wiperLayer.bounds = NSMakeRect(0, 0, 1, 61);
        
        _wiperLayer.contents = [NSImage imageNamed:@"wiper.png”]; // just a red 
vertical line
        _wiperLayer.anchorPoint = zeroPt;
        
        [[self layer] addSublayer:_wiperLayer];
        _wiperLayer.position = zeroPt;
         */

In order to see the wiper in 10.13, I had to move this code to the reposition 
method, like so:

//-----------------------------------------------------------------------
- (void)startWiperAtPct:(float)pct
//-----------------------------------------------------------------------
{

        CGPoint zeroPt = CGPointMake(0,0);
        
        self.layer.anchorPoint = zeroPt;
        
        if( _wiperLayer ){ // we have to add a new one to make it work, so have 
to get rid of the last one
                [_wiperLayer removeFromSuperlayer];
        }

        self.wiperLayer = [CALayer layer];
        [_wiperLayer setFrame:NSMakeRect(0, 0, 1, 61)];
        _wiperLayer.bounds = NSMakeRect(0, 0, 1, 61);
        
        _wiperLayer.contents = [NSImage imageNamed:@"wiper.png"];
        _wiperLayer.anchorPoint = zeroPt;
        [[self layer] addSublayer:_wiperLayer];
        _wiperLayer.position = zeroPt;
        
        
        CAAnimation* animation = [self.wiperLayer animationForKey:@"position"];
        
        if( animation && pct){
                DLOG(@"have animation: wiper resuming");

                [self resumeWiper];
        }
        
        else{
                if( animation )
                        [_wiperLayer removeAllAnimations];

                DLOG(@"wiper starting at pct: %f", pct);

                NSInteger startPixel = self.bounds.size.width * pct;
                CABasicAnimation* ba = [CABasicAnimation 
animationWithKeyPath:@"position"];
                
                ba.fromValue =  [NSValue valueWithPoint:CGPointMake(startPixel 
,0)];
                ba.toValue = [NSValue 
valueWithPoint:CGPointMake(self.bounds.size.width,0)];
                ba.duration = _currentDuration - (pct * _currentDuration);
                
                DLOG(@"Animation duration: %f", _currentDuration);
                
                [_wiperLayer addAnimation:ba forKey:@"position"];
                
                _wiperLayer.speed = 1.0;
        }
}

There are other methods for pausing and resuming, but they work the same in 
10.13.

Any light on this would be most welcome, as I hate not knowing why something 
stopped working!

Rob


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to