菜鸟教程小白 发表于 2022-12-12 16:49:44

ios - 使用 dispatch_semaphore 时执行 dispatch_after


                                            <p><p>当我想在 dispatch_afterblock 中执行代码时遇到问题。<br/>
首先,我在按下按钮时调用 UIActivityIndi​​cator 以便在屏幕上显示它,并且在 uiactivityindicator 开始运行后,我想执行服务器调用,当我从服务器获得响应时,我返回该值。< br/><br/>
问题是:当我调用我的 UIAtivityIndi​​cator 来运行,然后我调用我的服务器时,即使调用了 <code>;</code> 之后 UIActivityIndi​​cator 也不会显示在屏幕上,然后服务器操作被调用。<br/>
所以我决定使用 <code>dispatch_after</code> 以便在 de <code>;</code> 之后等待一段时间值,因此使用 <code>dispatch_semaphore</code> 告诉我操作何时完成,然后返回值。<br/><br/>
这里最大的问题是 <code>dispatch_after</code> 没有被调用。
这是我的代码,感谢您能帮助我解决这个问题或您想到的其他解决方案。<br/>
我想要完成的主要想法是,我想在服务器操作执行时显示一个 UIActivityIndi​​cator,当它完成时,我想在同一方法中返回该值。<br/><br/><br/></p>

<pre class="lang-c prettyprint-override"><code>- (BOOL)getUserSatatus {
   // This is when the UIActivityIndicator is starts running
   ;
   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(@&#34;This is where the server will call&#34;);
         // This is when I perform the service call and it returns a values that is
         // assigned to server response.
         serverResponse = ;
         // 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.
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>你说:</p>

<blockquote>
<p>The big problem here is that the dispatch_after is not called. </p>
</blockquote>

<p>是的,那是因为你用 <code>dispatch_semaphore_wait</code> 阻塞了主线程,所以 <code>dispatch_after</code> 永远没有机会在主线程上运行并且你死锁了。 </p>

<p>我们可以指导您解决此问题,但您的代码中根本不应该有同步网络调用或信号量(出于多种原因,不仅仅是为了您的事件指示器和解决您的死锁问题)。 </p>

<p>您应该删除这些同步网络请求,删除 <code>dispatch_after</code>,并删除信号量。如果您完成所有这些操作,而是遵循异步模式(例如使用完成 block ),那么您的事件指示器 View 内容将正常工作,并且您也不会出现任何死锁。</p>

<p>正确的答案是重构“后端管理器”以异步执行其请求(使用完成 block ),然后也使用带有 <code>getUserStatus</code> 方法的完成 block 模式。</p>

<p>例如,假设您将 <code>_backendManager</code> 的 <code>getStatus</code> 固定为异步行为:</p>

<pre><code>- (void)getStatusWithCompletion:(void (^)(BOOL))completion {
    NSMutableURLRequest *request = ...   // build the request however appropriate
    NSURLSessionTask *task = [ 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);
      });
    }];
    ;
}
</code></pre>

<p>然后您可以从您的问题中重构 <code>getUserStatus</code> 以获取完成处理程序:</p>

<pre><code>- (void)getUserStatusWithCompletion:(void (^)(BOOL))completion {
    // This is when the UIActivityIndicator is starts running
    ;

    [_backendManager getStatusWithCompletion:^(BOOL status){
      ;
      if (completion) completion(status);
    }
}
</code></pre>

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

<pre><code>[obj getUserStatusWithCompletion:^(BOOL success) {
    // use `success` here
}];

// but not here
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 使用 dispatch_semaphore 时执行 dispatch_after,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/33326220/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/33326220/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 使用 dispatch_semaphore 时执行 dispatch_after