1
votes

I have a pretty basic question: How do you choose between using UIView and CAShapeLayer when you want to draw shapes (I'm not talking about textfields, switches or other controls, just drawing)?

My understanding is that UIView (as part of UIKit) uses a normal CALayer under the hood to draw its content. If this is correct, then CAShapeLayer (or CALayer in general) would be the exact same thing, only without the extras UIKit gives you.

Then, when does using a UIView make sense, and when does using CAShapeLayer make sense?

Is CAShapeLayer faster? Is UIKit more optimised for gesture recognition or user interaction in general?


To give you more context, here's what I was trying to do when this question came up:

Illustration

I want these red circles to rotate around the center circle. However, the user should be able to tap on the red circles while they are rotating.

Here, I see two main options (there may be more) to add one of those red circles:

  1. Create a UIView, manipulate its layer's cornerRadius and rotate it using CGAffineTransform.
  2. Create a CAShapeLayer with a UIBezierPath. I could rotate it using CATransform3D

The only problem I have here is the user interaction. As it's constantly moving (rotating), I'd have to access the correct frame. I can do that using the presentation layer (which I think UIView is also using under the hood).

At this point, I'm not sure whether to use UIViews or CAShapeLayers. Also, I'm not sure if animating it this way is the correct way in this case. There may be better options that will also erase the question about which one to use.

Thanks for your thoughts about this.

1

1 Answers

1
votes

Quoting from Apple's doc

Layers are not a replacement for your app’s views—that is, you cannot create a visual interface based solely on layer objects. Layers provide infrastructure for your views. Specifically, layers make it easier and more efficient to draw and animate the contents of views and maintain high frame rates while doing so. However, there are many things that layers do not do. Layers do not handle events, draw content, participate in the responder chain, or do many other things. For this reason, every app must still have one or more views to handle those kinds of interactions.

In iOS, every view is backed by a corresponding layer object but in OS X you must decide which views should have layers. In OS X v10.8 and later, it probably makes sense to add layers to all of your views. However, you are not required to do so and can still disable layers in cases where the overhead is unwarranted and unneeded. Layers do increase your app’s memory overhead somewhat but their benefits often outweigh the disadvantage, so it is always best to test the performance of your app before disabling layer support.

When you enable layer support for a view, you create what is referred to as a layer-backed view. In a layer-backed view, the system is responsible for creating the underlying layer object and for keeping that layer in sync with the view. All iOS views are layer-backed and most views in OS X are as well. However, in OS X, you can also create a layer-hosting view, which is a view where you supply the layer object yourself. For a layer-hosting view, AppKit takes a hands off approach with managing the layer and does not modify it in response to view changes.

Read : https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreAnimationBasics/CoreAnimationBasics.html#//apple_ref/doc/uid/TP40004514-CH2-SW3

Now time for Some QNA

Question 1:

My understanding is that UIView (as part of UIKit) uses a normal CALayer under the hood to draw its content. If this is correct, then CAShapeLayer (or CALayer in general) would be the exact same thing, only without the extras UIKit gives you

Again Quoting Apple doc

Layer-backed views create an instance of the CALayer class by default, and in most cases you might not need a different type of layer object. However, Core Animation provides different layer classes, each of which provides specialized capabilities that you might find useful. Choosing a different layer class might enable you to improve performance or support a specific type of content in a simple way

Clearly when you try to draw various shapes using CAShapeLayer is beneficial in terms of performance when compared to CALayer.

Question 2

Is CAShapeLayer faster? Is UIKit more optimised for gesture recognition or user interaction in general?

Clearly Layers do not handle events, draw content, participate in the responder chain, or do many other things. So none of the layer can recognize user interactions no matter whether its CALayer or CAShapeLayer

Question 3

At this point, I'm not sure whether to use UIViews or CAShapeLayers

As you have specified in your question you want user interactions of red circles and because we are now aware of the fact that CAShapeLayer/CALayer will not respond to user interaction its pretty clear that you have to use UIView rather than layer.