使用dispatch_semaphore时执行dispatch_after

时间:2015-10-25 04:33:15

标签: ios objective-c-blocks grand-central-dispatch

当我想在dispatch_after块中执行代码时,我遇到了问题 首先,当按下按钮以便在屏幕上显示它并且在uiactivityindicator开始运行之后我调用UIActivityIndi​​cator时我想执行服务器调用,当我从服务器得到响应时我返回该值。

问题是:当我调用我的UIAtivityIndi​​cator运行并在之后进行服务器调用时,即使调用[UIActivityIndicatorInstance startAnimating];,UIActivityIndi​​cator也不会显示在屏幕上,之后调用服务器操作。登记/> 因此我决定使用dispatch_after以便在de [UIActivityIndicatorInstance startAnimating];之后等待一段时间。当我执行此操作时,问题变为我必须返回值时,因此使用{ {1}}告诉我操作何时完成然后返回值。

这里的一个大问题是dispatch_semaphore没有被调用。 这是我的代码,我感谢您可以帮助我解决这个问题或者您想到的其他解决方案 我想要完成的主要想法是我想在服务器操作执行时显示UIActivityIndi​​cator,当它完成时我想以同样的方法返回该值。


< / p>

dispatch_after

1 个答案:

答案 0 :(得分:2)

你说:

  

这里的一个大问题是没有调用dispatch_after。

是的,那是因为你用dispatch_semaphore_wait来阻止主线程,所以dispatch_after永远不会有机会在主线程上运行而你会陷入僵局。

我们可以引导您解决此问题,但您根本不应该在代码中使用同步网络调用或信号量(出于多种原因,不仅仅是因为您的活动指示器和解决您的死锁问题)。

您应删除这些同步网络请求,删除dispatch_after,然后删除信号量。如果你做了所有这些,而是​​遵循异步模式(比如使用完成块),那么你的活动指标视图内容将正常工作,你也不会有任何死锁。

正确的答案是重构“后端管理器”以异步方式执行其请求(使用完成块),然后使用完成块模式和getUserStatus方法。

例如,假设您修复了getStatus的{​​{1}}以异步行为:

_backendManager

然后你可以从你的问题中重构- (void)getStatusWithCompletion:(void (^)(BOOL))completion { NSMutableURLRequest *request = ... // build the request however appropriate NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { BOOL status = ...; // parse the response however appropriate dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(status); }); }]; [task resume]; } 以获得完成处理程序:

getUserStatus

然后需要获取用户状态的代码将执行以下操作:

- (void)getUserStatusWithCompletion:(void (^)(BOOL))completion {
    // This is when the UIActivityIndicator is starts running
    [Tools startActivityIndicator];

    [_backendManager getStatusWithCompletion:^(BOOL status){
        [Tools stopActivityIndicator];
        if (completion) completion(status);
    }
}