2011-04-11 45 views
2

雖然它不會很難旋轉起來我自己的這個方法,它不會是一樣有效Obj-C中的performSelector塊:onThread:?

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; 

有一個內置的方法與塊做到這一點?

如果沒有,是否有一種方法可以避免創建對象,將塊放在上面,並將它傳遞給選擇器方法?我也想知道在塊中訪問的數據是否會有問題...

+1

您是否在具體詢問如何在給定線程上運行塊或僅在非主線程上運行塊? – 2011-04-11 19:52:07

+0

Thanks @Brad Larson。它必須是一個特定的線程,因爲它是我的AsyncSocket的工作原理之一。 – 2011-04-11 20:37:36

+0

@Yar:有沒有你沒有使用GCDAsyncSocket的原因?它是[項目](http://code.google.com/p/cocoaasyncsocket/)本身的一部分,並且使用塊來實現,更不用說對它們提供很好的支持。它還有很多其他非常有用的功能(更大的SSL支持)等,您可能會覺得有用。 – 2011-04-11 22:37:59

回答

5

相當於performSelector:方法的塊是CFRunLoopPerformBlock - 您只需要獲得對該線程的參考CFRunLoop

查看Apple's documentation的功能並注意討論中的注意事項 - 之後您可能需要調用CFRunLoopWakeUp以便塊立即執行。

+0

男人,簡單! +1,因爲我找到了你所談論的所有東西。 – 2011-04-11 22:22:01

+0

我沒有時間來實現這個,所以我會在這裏寫下我的筆記:我有一個'NSThread'和一個塊。我通過調用'CFRunLoopGetCurrent'獲得'CFRunLoopRef',然後使用'CFRunLoopRef'和來自這裏的'kCFRunLoopCommonModes'中的常量調用'CFRunLoopPerformBlock' ... '此方法僅將塊排入隊列,不會自動喚醒指定的運行循環。因此,下一次運行循環喚醒以處理另一個輸入源時,會執行塊的執行。如果您希望立即執行該工作,則必須使用CFRunLoopWakeUp函數明確喚醒該線程。 – 2011-04-17 01:05:01

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]; 

正如在評論中提到尼克,它使用本地變量將在棧上創建一個塊。這意味着如果您選擇不等待完成,則需要使用[[myBlock copy] autorelease],否則可能會在調用它之前解除分配它。

+0

@Yar是的,它應該,謝謝指出。我會在帖子中修復它。 – ughoavgfhw 2011-04-11 22:11:14

+0

很棒的回答。有點不好意思,但是與'CFRunLoopPerformBlock'搞混了,這可能更好一些:不要搞新概念就有優勢。雖然......我必須得到CFRunLoopPerformBlock的東西...... :) – 2011-04-11 22:25:28

+1

請記住,塊對象從棧上開始,直到它們發送一個'copy'消息,所以類似'[NSArray arrayWithObjects:[[ myBlock copy] autorelease],arg1,arg2,nil];'通常是必須的。這裏可能沒有關係,因爲你有'waitUntilDone:YES',但是在其他情況下它會咬你。 – 2011-04-12 06:38:10