简体   繁体   中英

CALayer performance problem: animating a line anchored between two UIViews

I have an iPad app that has draggable UIViews contained in a larger parent UIView (which i'll call the main view). One of the features of the app is the ability to drag between two views to connect them. When dragging i render a line in a CALayer that is rooted on the view that you started dragging on and ends on the user's finger. If the user ends the drag on top of another view they become attached.

When views are attached there is a line permanently drawn between them.

So in the current implementation there are two CALayers which are sublayers of the main view. One is the linkLayer, which renders the existing links between views. the other is the linkLineLayer which renders the line the user is currently drawing w/ a drag action.

When dragging occurs and an new drag event comes in, i call [linkLineLayer setNeedsDisplay]. similarly, when a user is dragging a view around i call [linkLayer setNeedsDisplay].

the performance is terrible on the actual device, so im guessing that this isn't the way to go. What alternatives are there to draw lines between views (or points in a view) such that i can update them frequently when dragging a view or dragging a line between views without wrecking the framerate and hammering the device cpu?

Update So last night i went in and made two fixes that made a huge difference: 1.) all link lines are their own layer. as a view is being dragged around i refresh only the link lines associated w/ that specific view.
2.) updated the "dragging line" to be a layer that whose size is limited to the size of the line being rendered. i adjust the layer bounds as the user's finger is moving.

Have you tried rendering the lines as CAShapeLayer s? Instead of drawing the line yourself ans calling setNeedsDisplay all of the time, you can just set the path attribute of the CAShapeLayer and let it do the rest.

Core Animation handles CAShapeLayer s differently, and it can optimize the drawing of the path. If you just draw a path yourself in drawLayer:inContext: (or an equivalent) Core Animation has to treat the entire layer as an image because it has no idea what you've drawn. If you use a CAShapeLayer , Core Animation knows the path that you want to draw in advance, and it can optimize its rendering accordingly. You also don't have to worry about the size and position of the shape layer because the layer is just the path.

Also, an extra pointer, if you want to draw an open path (line) with no fill, you have to set the shape layer's fillColor property to nil . If you don't, it will automatically close the path and fill with a default color.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM