2011-02-09 66 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];