On Wed, Jan 29, 2014, at 11:44 AM, Seth Willits wrote: > > - ConnectionsLayer has a private property: @property int > nodePositionsDidChange; > - +needsDisplayForKey: returns YES for "nodePositionsDidChange" (calls > super for anything else) > - noteNodePositionsChanged calls: > [self addAnimation:[CABasicAnimation > animationWithKeyPath:@"nodePositionsDidChange"] > forKey:@"animateForNodePositionsChange"]; > > > The nodePositionsDidChange property itself is never set or get. It's > simply there so that we can "animate" it, and Core Animation will > recognize (via +needsDisplayForKey :) that while this property is > animating, the layer should be redisplayed. Boom. (It's a bit voodoo that > it can animate even though the value doesn't change at all, but there you > go.) > > > > The only "negative" part to this approach is that even if none of the > boxes change positions, if noteNodePositionsChanged is called then it > will redraw many times for whatever the duration of the animation is. So > for efficiency's sake, noteNodePositionsChanged should only be called if > a box's position actually did change. Ideally, we wouldn't need to call > noteNodePositionsChanged manually at all.
Interesting that you chose this approach. I haven't gotten around to writing it up yet, but the past day or so of thinking through the problem, but I was coming to the conclusion that the only way to get this to work reliably would be to not rely on implicit animations at all. Instead, when you wanted to animate the subtree, you'd need to add explicit CAAnimations to the entire tree. //begin @implementation MyView - (void)animateLayerTree { [CATransaction begin]; // Generate a CALayer -> NSValue(CGPoint) map NSDictionary *sublayerToPositionMap = [self _generateMapOfSublayersToNewPositions]; CAAnimationGroup *connectionsAnimGroup = [CAAnimationGroup animation]; for (CALayer *sublayer in sublayerToPositionMap.allKeys) { CGPoint oldPosition = sublayer.position; CGPoint newPosition = [sublayerToPositionMap objectForKey:sublayer].pointValue; sublayer.position = newPosition; CGPoint oldConnectionEndpoint = [_connectionsLayer convertPoint:oldPosition fromLayer:sublayer]; CGPoint newConnectionEndpoint = [_connectionsLayer convertPoint:newPosition fromLayer:sublayer]; [connectionsAnimGroup addAnimation:[MyConnectionsAnimation animationOfLineNamed:sublayer.name fromPoint:oldConnectionEndpoint toPoint:newConnectionEndpoint]; } // The connections layer returns YES for +needsDisplayForKey:@"connections" // TODO: Support retargeting animations mid-flight [_connectionsLayer addAnimation:connectionsAnimGroup forKey:@"connections"]; [CATransaction commit]; } //end This at least avoids the possibility that CA might stop sending -setNeedsDisplay for a key which never changes, and it feels less "magic". --Kyle Sluder _______________________________________________ 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