虽然为此启动我自己的方法并不困难,但它不如
那么有效- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
是否有内置的方法来执行此操作?
如果没有,有没有办法可以避免创建一个对象,将块放在它上面,并将其传递给选择器方法?我也想知道在块内访问的数据是否存在问题......
答案 0 :(得分:5)
由于块是作为objective-c对象实现的,因此您可以将其转换为id
并将其传递给performSelector:...
方法。要做你想做的事,你可以在NSObject上定义一个接受并调用块的类别。这是一个例子。它使用NSArray作为参数,以便您可以传递不确定数量的参数,并将它们传递给数组中的块。
typedef void (^PerformableBlock)(NSArray *arguments);
@implementation NSObject (PerformBlocks)
- (void)performBlockWithArray:(NSArray *)blockAndArguments {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
PerformableBlock theBlock = (PerformableBlock)[blockAndArguments objectAtIndex:0];
NSArray *blockArgs = [arguments subarrayWithRange:(NSRange){1,[arguments count] - 1}];
theBlock(blockArgs);
[pool release];
}
@end
然后,您可以使用与此类似的代码调用此方法:
PerformableBlock myBlock = ^(NSArray *args) {
NSLog(@"%@",args);
};
NSArray *array = [NSArray arrayWithObjects:(id)myBlock, arg1, arg2, nil];
[self performSelector:@selector(performBlockWithArray:) onThread:theThread withObject:array waithUntilDone:YES];
正如Nick在评论中所提到的,将在堆栈上创建一个使用局部变量的块。这意味着如果您选择不等到它完成,则需要在将[[myBlock copy] autorelease]
添加到数组时使用{{1}},或者可以在调用它之前将其释放。
答案 1 :(得分:5)
与performSelector:
方法等效的块是CFRunLoopPerformBlock
- 您只需要获得对该线程的CFRunLoop
的引用。
查看Apple's documentation函数并注意讨论中的警告 - 您可能希望之后调用CFRunLoopWakeUp
,以便立即执行块。