推荐的异步块设计模式?

时间:2012-07-31 19:10:59

标签: ios cocoa-touch cocoa design-patterns

我正在开发一款具有高度异步设计的iOS应用。在某些情况下,单个概念性“操作”可能会排队许多子块,这些子块将异步执行并异步接收它们的响应(调用远程服务器)。这些子块中的任何一个都可以在错误状态下完成执行。如果在任何子块中发生错误,则应取消任何其他子块,错误状态应该渗透到父级,并且应该执行父级的错误处理块。

我想知道在这样的环境中可能会推荐哪些设计模式和其他技巧?

我知道GCD的dispatch_group_async和dispatch_group_wait功能。这可能是这个应用程序设计中的一个缺陷,但我对dispatch_group_async没有好运,因为该组似乎对子块没有“粘性”。

提前致谢!

3 个答案:

答案 0 :(得分:5)

有一个WWDC视频(2012)可能会帮助你。它使用自定义NSOperationQueue并将异步块放在NSOperations内,这样您就可以保留块的句柄并取消剩余的排队块。

一个想法是让子块的错误处理来调用处理NSOperationQueue的类中的主线程上的方法。然后,班级可以适当地取消其余的。这样子块只需要知道自己的线程和主线程。这是视频的链接

https://developer.apple.com/videos/wwdc/2012/

该视频名为“在iOS上构建并发用户界面”。相关部分主要是在下半部分,但你可能想要观察整个事情,因为它很好地将它放在上下文中。

编辑:

如果可能的话,我建议在嵌入式块中处理响应,它将它很好地包装在一起,这就是我认为你想要的...

//Define an NSBlockOperation, and get weak reference to it
NSBlockOperation *blockOp = [[NSBlockOperation alloc]init];
__weak NSBlockOperation *weakBlockOp = blockOp;

//Define the block and add to the NSOperationQueue, when the view controller is popped
//we can call -[NSOperationQueue cancelAllOperations] which will cancel all pending threaded ops
[blockOp addExecutionBlock: ^{

    //Once a block is executing, will need to put manual checks to see if cancel flag has been set otherwise
    //the operation will not be cancelled. The check is rather pointless in this example, but if the
    //block contained multiple lines of long running code it would make sense to do this at safe points
    if (![weakBlockOp isCancelled]) {

        //substitute code in here, possibly use *synchronous* NSURLConnection to get
        //what you need. This code will block the thread until the server response
        //completes. Hence not executing the following block and keeping it on the 
        //queue.  
        __block NSData *temp;
        response = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];

        [operationQueue addOperationWithBlock:^{
            if (error) {
                  dispatch_async(dispatch_get_main_queue(), ^{
                        //Call selector on main thread to handle canceling
                        //Main thread can then use handle on NSOperationQueue
                        //to cancel the rest of the blocks 
                  });
            else {
                 //Continue executing relevant code....      
            }
        }];
    }
}];
[operationQueue addOperation:blockOp];

答案 1 :(得分:1)

自发布此问题以来,我遇到的一种模式是使用信号量将异步操作更改为同步操作。这非常有用。这篇博文更详细地介绍了这个概念。

http://www.g8production.com/post/76942348764/wait-for-blocks-execution-using-a-dispatch-semaphore

答案 2 :(得分:-1)

有许多方法可以在cocoa中实现异步行为。

GCD,NSOperationQueue,performSelectorAfterDelay,创建自己的线程。有适当的时间使用这些机制。在这里讨论的时间太长了,但你在帖子中提到的内容需要解决。

  

如果在任何子块中发生错误,则应取消任何其他子块,错误状态应该被渗透到父级,并且应该执行父级的错误处理块。

阻止无法在堆栈中抛出错误。期。