ios - 如何在iOS中使特定部分功能等待

标签 ios iphone objective-c objective-c-blocks nslock

我正在尝试执行共享操作,在该操作中我使用异步 block 调用函数,但在我的下一个 if 语句中,我需要获取在 block 中完成的值才能继续。这是我的代码,它将突出显示更多细节。我听说过 NSLock 并尝试使用它,但它没有用,可能是我在做一些锁,我对锁不太熟悉。

-(void) shareOperation
{
__block NSString *resultText;
BOOL continueSharing;
 NSLock *conditionLock=[[NSLock alloc] init];
         dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            [conditionLock lock];
        [self performSomeAsynchronousOperation completionBlock:^(NSError *tError, bool status)
         {
             dispatch_async(dispatch_get_main_queue(),
                            ^{

                                if (status)
                                {
                                    resultText = @"Operation completed. Would you like to continue?";

                                }
                                else
                                {
                                    resultText = @" Operation failed. Would you still like to continue?";
                                }
                                UIAlertView *result = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:[NSArray arrayWithObjects:@"OK",nil] onDismiss:^(int buttonIndex)
                                                       {
                                                           NSLog(@"selected button index: %d",buttonIndex);
                                                           if (buttonIndex == 0)
                                                           {
                                                               continueSharing=YES;
                                                               [conditionLock unlock];
                                                               NSLog(@"We are continuing sharing :)");
                                                           }
                                                       }onCancel:^{
                                                           continueSharing=NO;
                                                            [conditionLock unlock];
                                                           NSLog(@"cancelled");
                                                       }]; [result show];

                            });
         }];
        });
    }


    //should continue only after earlier if block finishes, ie after getting the continueSharing value

    if (continueSharing)
    {
        [self performSomeAnotherAsynchronousOperation];
    }

}

最佳答案

您可以使用信号量(其设计目的是让一个线程可以等待来自另一个线程的信号,这里需要),而不是使用锁(它只是为了确保不会同时访问某些共享资源)。

因此,您应该创建一个信号量:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

警报 View 完成 block 将发出该信号量的信号:
dispatch_semaphore_signal(semaphore);

以及您要在哪里等待该信号(在 performSomeAnotherAsynchronousOperation 之前):
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

我稍微调整了您的代码,但最值得注意的是,通过确保 dispatch_semaphore_wait 对其进行了更改,使其不会阻塞主队列(您永远不想这样做)在后台队列中完成。另请注意 dispatch_semaphore_signal不在 if 内陈述。这导致:
- (void)shareOperation
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        __block BOOL continueSharing = NO;
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        [self performSomeAsynchronousOperationWithCompletionBlock:^(NSError *tError, bool status){
            dispatch_async(dispatch_get_main_queue(),^{
                NSString *resultText;

                if (status)
                    resultText = @"Operation completed. Would you like to continue?";
                else
                    resultText = @"Operation failed. Would you still like to continue?";

                UIAlertView *alertView = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:@[@"OK"] onDismiss:^(int buttonIndex) {
                    NSLog(@"selected button index: %d",buttonIndex);
                    if (buttonIndex == 0) {
                        continueSharing = YES;
                        NSLog(@"We are continuing sharing :)");
                    }
                    dispatch_semaphore_signal(semaphore);
                } onCancel:^{
                    dispatch_semaphore_signal(semaphore);
                    NSLog(@"cancelled");
                }];

                [alertView show];
            });
        }];

        // should continue only after earlier if block finishes, ie after getting the continueSharing value

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        if (continueSharing)
            [self performSomeAnotherAsynchronousOperation];
    });
}

更好的是,您不应该使用任何阻塞机制,如信号量(当然不在主队列上),而应该简单地让警报 View 的完成 block 直接启动流程的下一步。我了解您说这在您的场景中不实用,但通常是处理这些场景的正确方法。

关于ios - 如何在iOS中使特定部分功能等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21184075/

相关文章:

ios - 如何将 iOS8 代码片段添加到 Adob​​e Air iOS app.xml?

iphone - 使用 AddressBookUI 访问联系人添加到 iPhone 地址簿的日期

iphone - 这段代码是否有可能在内存方面引起任何问题?

objective-c - 在 ARC 下返回 NSString 时如何避免临时对象

ios - 如何在 Switch 语句中使用可选整数

ios - SceneKit Material 中充满了随机图案,为什么?

iphone - 无法检测 iPhone 上的纵向方向

iphone - 更改 View 时 ASIHTTPRequest 异步崩溃

objective-c - 如何以编程方式快速检查 iphone 4 和 iphone 5 的屏幕尺寸

ios - 如何以编程方式添加大小类自定义