当我想在dispatch_after块中执行一段代码时,我遇到了问题。
首先,当按下按钮以便在屏幕上显示它时,我正在调用一个UIActivityIndicator,在uiactivity指示器开始运行之后,我想要执行一个服务器调用,当我从服务器得到响应时,返回这个值。
问题是:当我调用我的UIAtivityIndicator来运行,然后进行服务器调用时,即使在调用[UIActivityIndicatorInstance startAnimating];和调用服务器操作之后,[UIActivityIndicatorInstance startAnimating];也不会在屏幕上显示。
因此,我决定使用dispatch_after,以便在de [UIActivityIndicatorInstance startAnimating];之后等待一段时间,当我这样做时,问题就变成了当我必须返回值时,因此使用dispatch_semaphore来告诉我操作什么时候完成,然后返回值。
这里的大问题是dispatch_after没有被调用。这是我的代码,我很感谢你能帮我解决这个问题或者你想要的其他解决方案。
我想要实现的主要思想是,在服务器操作执行时显示一个UIActivityIndicator,当它完成时,我希望在相同的方法中返回该值。
- (BOOL)getUserSatatus {
// This is when the UIActivityIndicator is starts running
[Tools startActivityIndicator];
double delayInSeconds = 0.5;
// This is used to save server response.
__block BOOL serverResponse;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_time_t executionTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
// I want to execute the server call after a perios of time in order to show first de indicator on screen
dispatch_after(executionTime, dispatch_get_main_queue(), ^{
NSLog(@"This is where the server will call");
// This is when I perform the service call and it returns a values that is
// assigned to server response.
serverResponse = [_backendManager getStatus];
// This is the signal for the semaphore in order to execute the next lines.
dispatch_semaphore_signal(semaphore);
});
// Wait until the signal in order to execute the next line.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return serverResponse; // Here will be the server return response.
}发布于 2015-10-25 05:52:16
你说:
这里的大问题是dispatch_after没有被调用。
是的,这是因为您用dispatch_semaphore_wait阻塞了主线程,所以dispatch_after从来没有机会在主线程上运行,而且是死锁的。
我们可以向您介绍解决这些问题的方法,但是您确实不应该在代码中使用同步网络调用或信号量(原因很多,不仅仅是因为您的活动指示器和解决您的死锁问题)。
您应该删除这些同步网络请求,删除dispatch_after,并删除信号量。如果您这样做,并且遵循异步模式(比如使用完成块),那么您的活动指示器视图就会正常工作,您也不会有任何死锁。
正确的答案是重构“后端管理器”以异步执行其请求(使用完成块),然后将完成块模式与getUserStatus方法一起使用。
例如,假设您修复了_backendManager的_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);
}
}然后,需要获得用户状态的代码将执行如下操作:
[obj getUserStatusWithCompletion:^(BOOL success) {
// use `success` here
}];
// but not herehttps://stackoverflow.com/questions/33326220
复制相似问题