Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
369 views
in Technique[技术] by (71.8m points)

iphone - Using CALayer Delegate

I have a UIView whose layers will have sublayers. I'd like to assign delegates for each of those sublayers, so the delegate method can tell the layer what to draw. My question is:

What should I provide as CALayer's delegate? The documentation says not to use the UIView the layers reside in, as this is reserved for the main CALayer of the view. But, creating another class just to be the delegate of the CALayers I create defeats the purpose of not subclassing CALayer. What are people typically using as the delegate for CALayer? Or should I just subclass?

Also, why is it that the class implementing the delegate methods doesn't have to conform to some sort of CALayer protocol? That's a wider overarching question I don't quite understand. I thought all classes requiring implementation of delegate methods required a protocol specification for implementers to conform to.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Preferring to keep the layer delegate methods in my UIView subclass, I use a basic re-delegating delegate class. This class can be reused without customization, avoiding the need to subclass CALayer or create a separate delegate class just for layer drawing.

@interface LayerDelegate : NSObject
- (id)initWithView:(UIView *)view;
@end

with this implementation:

@interface LayerDelegate ()
@property (nonatomic, weak) UIView *view;
@end

@implementation LayerDelegate

- (id)initWithView:(UIView *)view {
    self = [super init];
    if (self != nil) {
        _view = view;
    }
    return self;
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
    NSString *methodName = [NSString stringWithFormat:@"draw%@Layer:inContext:", layer.name];
    SEL selector = NSSelectorFromString(methodName);
    if ([self.view respondsToSelector:selector] == NO) {
        selector = @selector(drawLayer:inContext:);
    }

    void (*drawLayer)(UIView *, SEL, CALayer *, CGContextRef) = (__typeof__(drawLayer))objc_msgSend;
    drawLayer(self.view, selector, layer, context);
}

@end

The layer name is used to allow for per-layer custom draw methods. For example, if you have assigned a name to your layer, say layer.name = @"Background";, then you can implement a method like this:

- (void)drawBackgroundLayer:(CALayer *)layer inContext:(CGContextRef)context;

Note, your view will need a strong reference the instance of this class, and it can be used as the delegate for any number of layers.

layerDelegate = [[LayerDelegate alloc] initWithView:self];
layer1.delegate = layerDelegate;
layer2.delegate = layerDelegate;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...