同步回调 - 阻止与GCD队列

时间:2013-10-11 04:57:15

标签: objective-c objective-c-blocks

我是异步回调的新手,并且给出了不同的建议。我需要执行异步回调,经过几个小时的研究后,我仍然不知道是否应该使用块或GCD和队列。任何指针都会受到欢迎。

行。所以我真正要问的是:

"为了使用'异步'回调,我需要使用GCD和队列吗?"

我从答案中收集的是答案是内绝对 GCD 队列

我的困惑源于这样一个事实:我得到的方向是我所需要的只是一个块,如下面的代码:

[UIView animateWithDuration:.4f
                 animations:^{
                     flashView.alpha = 0.f;
                 }
                 completion:^(BOOL finished){
                     [flashView removeFromSuperview];
                 }
 ];

但我在答案中看到的是,上述方块不足以使异步&#39;回调。相反,我 DO 实际上需要在中使用 GCD 队列,如下面的代码:< / p>

- (void)invokeAsync:(id (^)(void))asyncBlock resultBlock:(void (^)(id))resultBlock errorBlock:(void (^)(id))errorBlock {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        id result = nil;
        id error = nil;
        @try {
            result = asyncBlock();
        } @catch (NSException *exception) {
            NSLog(@"caught exception: %@", exception);
            error = exception;
        }
        // tell the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            NSAutoreleasePool *secondaryPool = [[NSAutoreleasePool alloc] init];
            if (error != nil) {
                errorBlock(error);
            } else {
                resultBlock(result);
            }
            [secondaryPool release];
        });
        [pool release];
    });
}

2 个答案:

答案 0 :(得分:3)

异步回调是指当前线程继续执行语句,并在不同的线程中分离执行代码以便以后运行的。

有几种技术可以实现这一目标。在这个例子中,我用4种不同的异步方式调用方法cacheImage:,带参数图像(只是一个例子)。

// 1. NSThread
[NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:self withObject:image];

// 2. performSelector...
[self performSelectorInBackground:@selector(cacheImage:) withObject:image];

// 3. NSOperationQueue
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(cacheImage:) object:image];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];

// 4. GCD
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self cacheImage:image];
});

到目前为止,更简单的方法是使用GCD,因为它已经有一个可供您使用的线程,而不必自己使用其他选项创建它。

但是,因为块是作为对象实现的,所以你确实可以使用没有GCD的块,例如:

// block definition
typedef void (^hello_t)();

// method that uses a block as parameter
-(void) runBlock:(hello_t)hello {
    hello();
}

// asynchronous execution of a block
[NSThread detachNewThreadSelector:@selector(runBlock) toTarget:self withObject:^(){
    NSLog(@"hi");
}];

PS:您不需要手动使用NSAutoreleasePool,除非您创建了许多对象并且您想立即释放内存。此外,@ try @catch很少用于Objective-C

答案 1 :(得分:2)

这里没有任何混淆点。 GCD也有块执行。 GCD API,支持在系统的Unix级别上异步执行操作。

块对象是C级语法和运行时功能。它们类似于标准C函数,但除了可执行代码之外,它们还可能包含对自动(堆栈)或托管(堆)内存的变量绑定。因此,块可以维护一组状态(数据),以便在执行时可以用来影响行为。

Apple设计的块的明确目标是为Grand Central Dispatch线程体系结构编写程序更容易,尽管它独立于该体系结构,并且可以像其他语言中的闭包一样使用。 Apple已经在他们自己的GNU Compiler Collection分支和Clang LLVM编译器前端中实现了块。语言运行时库对块的支持也可作为LLVM项目的一部分。

因此,在相同功能的情况下,您可以使用其中任何一个。