为了后代/完整性......这里有两个完整的示例,说明如何实现这种可笑的多功能“做事方式”。 @Robert 的回答非常简洁和正确,但在这里我还想展示实际“定义”块的方法。
@interface ReusableClass : NSObject
@property (nonatomic,copy) CALayer*(^layerFromArray)(NSArray*);
@end
@implementation ResusableClass
static NSString const * privateScope = @"Touch my monkey.";
- (CALayer*(^)(NSArray*)) layerFromArray {
return ^CALayer*(NSArray* array){
CALayer *returnLayer = CALayer.layer
for (id thing in array) {
[returnLayer doSomethingCrazy];
[returnLayer setValue:privateScope
forKey:@"anticsAndShenanigans"];
}
return list;
};
}
@end
傻吗? 是的。有用吗? 是的。这是一种不同的“更原子”的设置属性的方式......以及一个非常有用的类......
@interface CALayoutDelegator : NSObject
@property (nonatomic,strong) void(^layoutBlock)(CALayer*);
@end
@implementation CALayoutDelegator
- (id) init {
return self = super.init ?
[self setLayoutBlock: ^(CALayer*layer){
for (CALayer* sub in layer.sublayers)
[sub someDefaultLayoutRoutine];
}], self : nil;
}
- (void) layoutSublayersOfLayer:(CALayer*)layer {
self.layoutBlock ? self.layoutBlock(layer) : nil;
}
@end
这说明了通过访问器设置块属性(尽管在 init 内部,这是一个值得商榷的冒险实践..)与第一个示例的“非原子”“getter”机制。在任何一种情况下......“硬编码”实现总是可以被覆盖,每个实例..一个 lá..
CALayoutDelegator *littleHelper = CALayoutDelegator.new;
littleHelper.layoutBlock = ^(CALayer*layer){
[layer.sublayers do:^(id sub){ [sub somethingElseEntirely]; }];
};
someLayer.layoutManager = littleHelper;
另外..如果你想在一个类别中添加一个块属性......说你想使用一个块而不是一些老派的目标/动作“动作”......你可以使用关联的值来,好吧..关联块。
typedef void(^NSControlActionBlock)(NSControl*);
@interface NSControl (ActionBlocks)
@property (copy) NSControlActionBlock actionBlock; @end
@implementation NSControl (ActionBlocks)
- (NSControlActionBlock) actionBlock {
// use the "getter" method's selector to store/retrieve the block!
return objc_getAssociatedObject(self, _cmd);
}
- (void) setActionBlock:(NSControlActionBlock)ab {
objc_setAssociatedObject( // save (copy) the block associatively, as categories can't synthesize Ivars.
self, @selector(actionBlock),ab ,OBJC_ASSOCIATION_COPY);
self.target = self; // set self as target (where you call the block)
self.action = @selector(doItYourself); // this is where it's called.
}
- (void) doItYourself {
if (self.actionBlock && self.target == self) self.actionBlock(self);
}
@end
现在,当你制作一个按钮时,你不必设置一些IBAction 戏剧..只需关联创建时要完成的工作......
_button.actionBlock = ^(NSControl*thisButton){
[doc open]; [thisButton setEnabled:NO];
};
这种模式可以应用OVER 和OVER 到 Cocoa API。使用属性将代码的相关部分更紧密地结合在一起,消除复杂的委托范例,并利用对象的力量,而不仅仅是充当愚蠢的“容器”。