2011-02-09 115 views
8

我最新應用程序的體系結構的核心原則之一是我將調用應用程序模型上的方法,這將是異步並接受失敗和成功方案塊。調用模塊方法,將在主線程上運行塊

即,UI用2個塊調用模型方法,一個用於成功,一個用於失敗。

這很好,因爲原始調用的上下文被保留,但是塊本身在後臺線程上被調用。有沒有在主線程上調用塊?

希望我已經發現它,如果沒有,基本上,我的模型方法是異步的,立即返回,並創建一個新的線程運行操作。一旦操作返回,我將調用一個塊來處理返回的數據,然後我需要調用塊在UI內調用定義的成功場景。但是,應該在主線程中調用在UI中定義的成功和失敗場景塊,因爲我需要與UI元素進行交互,而這些UI元素只應在我相信的主線程上完成。

千恩萬謝

回答

36

像這樣的東西可能是你追求的:

- (void) doSomethingWhichTakesAgesWithArg: (id) theArg 
          resultHandler: (void (^)(BOOL, id, NSError *)) handler 
{ 
    // run in the background, on the default priority queue 
    dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
     id someVar = [theArg computeSomething]; 

     NSError * anError = nil; 
     [someVar transmuteSomehowUsing: self error: &anError]; 

     // call the result handler block on the main queue (i.e. main thread) 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // running synchronously on the main thread now -- call the handler 
      handler((error == nil), theArg, anError); 
     }); 
    }); 
} 
5

NSObject中有一個方法:

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 

創建需要的NSDictionary參數便利類中的方法,將永遠存在(如您的應用程序委託,或一個單獨的對象) ,包了塊及其參數成的NSDictionary的NSArray或和呼叫

[target performSelectorOnMainThread:@selector(doItSelector) withObject:blockAndParameters waitUntilDone:waitOrNot]; 
10

如果您正在使用GCD,您可以使用「獲取主隊列」:

dispatch_queue_t dispatch_get_main_queue() 

在異步調度中調用它。即

dispatch_async(dispatch_get_main_queue(), ^{ 
    /* Do somthing here with UIKit here */ 
}) 

上面的示例塊可能在異步背景隊列中運行,示例代碼會將UI工作發送到主線程。

6

類似的方法也適用與NSOperationQueue

NSBlockOperation *aOperation = [NSBlockOperation blockOperationWithBlock:^ 
{ 
    if (status == FAILURE) 
    { 
     // Show alert -> make sure it runs on the main thread 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^ 
     { 
      UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Alert" message:@"Your action failed!" delegate:nil 
             cancelButtonTitle:@"Ok" otherButtonTitles:nil] autorelease]; 
      [alert show]; 
     }]; 
    } 
}]; 

// myAsyncOperationQueue is created somewhere else 
[myAsyncOperationQueue addOperation:aOperation];