2012-05-19 53 views
9

我正在尝试构建一个绘制文本的特殊图层。这TWFlapLayer有一个属性串作为一个属性:自定义属性更改时重绘自定义CALayer子类

TWFlapLayer.h

@interface TWFlapLayer : CALayer 
@property(nonatomic, strong) __attribute__((NSObject)) CFAttributedStringRef attrString; 
@end 

TWFlapLayer.m被合成:

@implementation TWFlapLayer 

@synthesize attrString = _attrString; 

/* overwrite method to redraw the layer if the string changed */ 

+ (BOOL)needsDisplayForKey:(NSString *)key 
{ 
    if ([key isEqualToString:@"attrString"]){ 
     return YES; 
    } else { 
     return NO; 
    } 
} 

- (void)drawInContext:(CGContextRef)ctx 
{ 
    NSLog(@"%s: %@",__FUNCTION__,self.attrString); 
    if (self.attrString == NULL) return; 
    /* my custom drawing code */ 
} 

我的目的是使该层在使用我的自定义绘制方法自动重绘如果使用合成的setter方法更改attrString属性。但是从放置在drawInContext:方法中的NSLog语句中,我发现图层是而不是重绘。

放置一个断点在needsDisplayForKey方法我确信它当被问及对attrString键返回YES。

我现在改变这样

// self.frontString is a NSAttributedString* that is why I need the toll-free bridging 
self.frontLayer.attrString = (__bridge CFAttributedStringRef) self.frontString; 

//should not be necessary, but without it the drawInContext method is not called 
[self.frontLayer setNeedsDisplay]; // <-- why is this still needed? 

我的CALayer的头文件抬头类方法定义needsDisplayForKey的attrString,但在我看来,这是我想使用的方法或我错过了重要的一点吗?

CALayer.h

/* Method for subclasses to override. Returning true for a given 
* property causes the layer's contents to be redrawn when the property 
* is changed (including when changed by an animation attached to the 
* layer). The default implementation returns NO. Subclasses should 
* call super for properties defined by the superclass. (For example, 
* do not try to return YES for properties implemented by CALayer, 
* doing will have undefined results.) */ 

+ (BOOL)needsDisplayForKey:(NSString *)key; 

摘要

当自定义属性attrString发生变化,标志着needsDisplayForKey:为什么不重绘我的层?

回答

14

CALayer.h还说:

/* CALayer implements the standard NSKeyValueCoding protocol for all 
* Objective C properties defined by the class and its subclasses. It 
* dynamically implements missing accessor methods for properties 
* declared by subclasses. 

显然,needsDisplayForKey:机制依赖的CALayer的动态实现的访问方法。因此,改变这种:

@synthesize attrString = _attrString; 

@dynamic attrString; 
+0

这是伟大的!那就是诀窍。 “CALayer.h”真的是一个巨大的文件,有点尴尬,我错过了这一点。 – GorillaPatch

+0

@ kurt-revis我有类似的问题和@dynamic工作正常,谢谢。但是,你能否解释为什么初始渲染不会发生在我身上,即使我在' - (id)init'方法中设置了初始值。 needsDisplayForKey不会在'init'中触发。 – Andy

+0

您是否尝试过在'init'中调用'-setNeedsDisplay'? – ipmcc