在我希望支持块的所有事情中,NSUndoManager好奇地似乎没有这样做。是否存在一些固有的原因,或者苹果公司是否根本没有将这一点API现代化?
特别是我想在NSObject上定义一个方法,
- (void)performBlock {
void (^block)(void) = (id)self;
block();
}
为了能够打电话,
[[undoManager prepareWithInvocationTarget:^{
NSLog( @"hello world" );
}] performBlock];
我错过了什么吗?这有什么不对吗?
(受到2009年Mike Ash article的启发,建议不定义块上的方法。我也在那里发表评论。)
答案 0 :(得分:2)
我认为迈克的主要论点是它使代码难以阅读,而不是这个想法存在根本问题。
但是,我发现你写的内容存在一些问题。首先,你在NSObject上添加了一个类别方法,但是如果你在一个不是块的对象上调用它,它就会崩溃。也许有一种方法可以解决这个问题,比如让performBlock
方法在非块上调用时什么都不做,或者至少在崩溃之前记录错误。我不完全是这样的。
此外,块从堆栈开始,因此您需要先复制它们,然后再将它们传递给一个方法,以便稍后执行它们。编写的方法可以解决这个问题。据推测,-[NSUndoManager prepareWithInvocationTarget:]
不会复制传入的目标。因此,您需要自己复制该块(使用-copy
或Block_copy()
),然后再将其传入:
void (^block)(void) = [^{
NSLog(@"hello world");
} copy];
[[undoManager prepareWithInvocationTarget:block] performBlock];
[block release];
至少在ARC的早期版本中,这仍然是一个问题,因为块被传递到期望id
的方法中(如Mike Ash的ARC article的块部分所述)。也许它已被修复?我不指望它......