使用CALayer委托

Sha*_*ram 34 iphone calayer

我有一个UIView,其图层将有子图层.我想为每个子图层分配代理,因此委托方法可以告诉图层要绘制什么.我的问题是:

作为CALayer的代表,我应该提供什么?文档说不要使用层所在的UIView,因为这是为视图的主CALayer保留的.但是,创建另一个类只是为了成为我创建的CALayers的代表,这就失去了不继承CALayer的目的.人们通常使用什么作为CALayer的代表?或者我应该只是亚类?

另外,为什么实现委托方法的类不必遵循某种CALayer协议?这是一个我不太了解的更广泛的首要问题.我认为所有需要实现委托方法的类都需要协议规范,以便实现者遵守.

Dav*_*Lee 30

我希望在我的UIView子类中保留层委托方法,我使用一个基本的重新委派委托类.此类可以在不进行自定义的情况下重复使用,从而无需为CALayer创建子类或仅为图层绘制创建单独的委托类.

@interface LayerDelegate : NSObject
- (id)initWithView:(UIView *)view;
@end
Run Code Online (Sandbox Code Playgroud)

有了这个实现:

@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
Run Code Online (Sandbox Code Playgroud)

图层名称用于允许每层自定义绘制方法.例如,如果您已为图层指定了名称layer.name = @"Background";,那么您可以实现如下方法:

- (void)drawBackgroundLayer:(CALayer *)layer inContext:(CGContextRef)context;
Run Code Online (Sandbox Code Playgroud)

请注意,您的视图需要强大的引用此类的实例,并且它可以用作任意数量的层的委托.

layerDelegate = [[LayerDelegate alloc] initWithView:self];
layer1.delegate = layerDelegate;
layer2.delegate = layerDelegate;
Run Code Online (Sandbox Code Playgroud)


Fel*_*xyz 28

最轻微的解决方案是在文件中创建一个小助手类作为使用CALayer的UIView:

在MyView.h中

@interface MyLayerDelegate : NSObject
. . .
@end
Run Code Online (Sandbox Code Playgroud)

在MyView.m中

@implementation MyLayerDelegate
- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx
{
. . .
}
@end
Run Code Online (Sandbox Code Playgroud)

只需将它们放在文件的顶部,紧接在#import指令下面.这样,感觉更像是使用"私有类"来处理绘图(虽然它不是 - 委托类可以由导入标题的任何代码实例化).

  • 您可以将`@interface`放在.m文件中,以获得更好的_private class_感觉.如果你需要引用.h文件中的类(例如,对于ivar),你可以使用像@class MyLayerDelegate;这样的前向声明. (8认同)

Mat*_*ong 9

看一下正式与非正式协议文档.CALayer正在实现一个非正式协议,这意味着您可以将任何对象设置为其委托,并通过检查特定选择器的委托(即-respondsToSelector)来确定它是否可以向该委托发送消息.

我通常使用我的视图控制器作为相关图层的委托.