Obj-C中的块for performSelector:onThread:?

Dan*_*ark 2 objective-c ios

虽然为此不必为自己的方法编制起来,但效率并不高

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
Run Code Online (Sandbox Code Playgroud)

是否有一个内置的方法用块来做到这一点?

如果没有,有没有办法可以避免创建一个对象,将块放在它上面,并将其传递给选择器方法?我也想知道在块内访问的数据是否存在问题...

ugh*_*fhw 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
Run Code Online (Sandbox Code Playgroud)

然后,您将使用与此类似的代码调用此方法:

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

正如Nick在评论中所提到的,将在堆栈上创建使用局部变量的块.这意味着[[myBlock copy] autorelease]如果您选择不等到它完成,则需要在将其添加到数组时使用,或者可以在调用之前将其释放.


Nic*_*son 5

相当于该performSelector:方法的块是CFRunLoopPerformBlock- 你只需要获得对该线程的引用CFRunLoop.

看一下Apple关于该功能的文档并注意讨论中的警告 - 您可能希望CFRunLoopWakeUp事后调用,以便立即执行该块.