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 que
I prefer the following solution. I would like to use the drawLayer:inContext:
method of the UIView to render a subview that I might add without adding extra classes all over the place. My solution is as follows:
Add the following files to your project:
UIView+UIView_LayerAdditions.h with contents:
@interface UIView (UIView_LayerAdditions)
- (CALayer *)createSublayer;
@end
UIView+UIView_LayerAdditions.m with contents
#import "UIView+UIView_LayerAdditions.h"
static int LayerDelegateDirectorKey;
@interface LayerDelegateDirector: NSObject{ @public UIView *view; } @end
@implementation LayerDelegateDirector
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
[view drawLayer:layer inContext:ctx];
}
@end
@implementation UIView (UIView_LayerAdditions)
- (LayerDelegateDirector *)director
{
LayerDelegateDirector *director = objc_getAssociatedObject(self, &LayerDelegateDirectorKey);
if (director == nil) {
director = [LayerDelegateDirector new];
director->view = self;
objc_setAssociatedObject(self, &LayerDelegateDirectorKey, director, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return director;
}
- (CALayer *)createSublayer
{
CALayer *layer = [CALayer new];
layer.contentsScale = [UIScreen mainScreen].scale;
layer.delegate = [self director];
[self.layer addSublayer:layer];
[layer setNeedsDisplay];
return layer;
}
@end
Now add the header to your .pch
file. If you add a layer using the createSublayer
method, it will automagically show up without bad allocs in the override to drawLayer:inContext:
. As far as I know the overhead of this solution is minimal.
A note regarding "helper" classes for use as a layer's delegate (with ARC at least):
Make sure you store a "strong" reference to your alloc/init'd helper class (such as in a property). Simply assigning the alloc/init'd helper class to the delegate seems to cause crashes for me, presumably because mylayer.delegate is a weak reference to your helper class (as most delegates are), so the helper class gets freed up before the layer can use it.
If I assign the helper class to a property, then assign it to the delegate, my weird crashes go away, and things behave as expected.