菜鸟教程小白 发表于 2022-12-13 10:34:57

ios - 如何阻止代码等待连接


                                            <p><p>我一直在为一些 sensorTag 提供新的 API。我需要等待连接解决,否则我的代码将在第一次运行时失败。我有以下代码片段:</p>

<pre><code>- (void)viewDidLoad {
;

self.sensorGyro = ;
if(self.sensorGyro){
    while (!self.sensorGyro.client.isDeviceConnected) {
      NSLog(@&#34;Awaiting connection&#34;);
    }//Check that connection has been made

    NSLog(@&#34;connection UP&#34;);

      [self.sensorGyro.client.sensorManager startGyroUpdatesToQueue:nil errorRef:nil withHandler:^(MSBSensorGyroData *GyroData, NSError *error) {
            NSLog(@&#34;Starting updates&#34;);
            self.currentGyroLabel.text = ;
      }];
</code></pre>

<p>最初我没有 while 循环。我使用了 2-3 秒的 dispatch_after 调用。但是我觉得等待固定时间不好,最好是连接后继续。但是当我使用 while 循环时,我的应用程序会停止并停止工作。没有崩溃,只是停下来。谁能告诉我为什么会这样。因为我已经验证了连接只需要 2 秒,我没有看到执行 while 循环的问题?另外,有没有更好的方法来“等待”东西完成/变干。</p>

<p>提前致谢</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p><code>MSBSensorUV</code> 类正在启动一些异步连接过程。</p>
<ol>
<li><p>如果您要循环等待状态更改,您可以将其分派(dispatch)到后台线程(正如 Luke 隐晦地建议的那样)。这可以防止应用阻塞主线程。</p>
<p>问题是你仍然有一个线程被捆绑在一个浪费的练习中,不断地轮询以查看 <code>isDeviceConnected</code> 是否为真。这就像一个 child 在汽车后座上不断问“我们到了吗?”</p>
</li>
<li><p>更好的是,您可以采用事件驱动模式,例如使用 Matteo 建议的 KVO。这样,您将在 <code>isDeviceConnected</code> 属性更改时收到通知,而不是此代码不断轮询。</p>
<p>如果您遇到一个不提供完成 block 但会异步更改某些属性的类,这会更有效,并且是一种很好的方法。</p>
</li>
<li><p>最好,因为 <code>MSBSensorUV</code> 是您自己的类,您可以重构它以提供一个连接完整的处理程序 block 。这样,您就可以避免上述方法带来的复杂性。</p>
</li>
</ol>
<hr/>
<p>离线,您分享了一点 <code>MSBSensorUV</code> 实现:</p>
<pre><code>+ (MSBSensorUV *)createObjectUV{
    static MSBSensorUV *UVObject;
    static dispatch_once_t once_token;
    dispatch_once(&amp;once_token, ^{
      UVObject = [init];
    });
    return UVObject;
}

- (MSBSensorUV *)init{
    self = ;
    if(self){
      .delegate = self;
      NSArray *clients = [ attachedClients];
      self.client = ;
      if(self.client == nil){
            //no bands attached
            return nil;
      }
      [ connectClient:self.client];
    }
    return self;
}
</code></pre>
<p>首先,<code>createObjectUV</code> 正在创建一个单例,因此您应该将其重命名为 <code>sharedSensor</code> 之类的名称(使用 <code>shared</code> 的前缀可以清楚地表明你正在处理一个单例):</p>
<pre><code>+ (instancetype)sharedSensor {
    static MSBSensorUV *uvObject;
    static dispatch_once_t once_token;
    dispatch_once(&amp;once_token, ^{
      uvObject = [ init];
    });
    return uvObject;
}
</code></pre>
<p>其次,<code>init</code>不应启动连接。</p>
<pre><code>- (instancetype)init {
    self = ;
    if (self) {
      .delegate = self;
      NSArray *clients = [ attachedClients];
      self.client = ;
      if(self.client == nil){
            //no bands attached
            return nil;
      }
      // [ connectClient:self.client];
    }
    return self;
}
</code></pre>
<p>坦率地说,在单例的上下文中,如果没有附加带,则返回 <code>nil</code> 的概念可能没有意义(因为一旦将其设置为 <code>nil</code>,在您终止应用程序之前,您永远无法再次访问此单例)。所以你可能也想从 <code>init</code> 中提取这个逻辑,但我会让你自己解决这个问题。</p>
<p>第三,您将为连接完成处理程序声明一个属性:</p>
<pre><code>@property (nonatomic, copy) void (^connectionCompletionHandler)(BOOL success, NSError *);
</code></pre>
<p>第四,您将创建一个 <code>connectionWithCompletionHandler</code> 方法,例如:</p>
<pre><code>- (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *error))block
{
    self.connectionCompletionHandler = block;
   
    [ connectClient:self.client];
}
</code></pre>
<p>然后您的连接委托(delegate)方法将调用此完成处理程序,例如<code>clientDidConnect</code> 会调用:</p>
<pre><code>if (self.connectionCompletionHandler) {
    self.connectionCompletionHandler(TRUE, nil);
    self.connectionCompletionHandler = nil;
}
</code></pre>
<p>而<code>didFailToConnectWithError</code>会报失败:</p>
<pre><code>if (self.connectionCompletionHandler) {
    self.connectionCompletionHandler(FALSE, error);
    self.connectionCompletionHandler = nil;
}
</code></pre>
<p>最后,回到你的原始代码示例,它看起来像:</p>
<pre><code>- (void)viewDidLoad {
    ;
   
    self.sensorGyro = ;
    [self.sensorGyro connectWithCompletionHandler:^(BOOL success, NSError *error) {
      if (success) {
            NSLog(@&#34;connection UP&#34;);
            [self.sensorGyro.client.sensorManager startGyroUpdatesToQueue:nil errorRef:nil withHandler:^(MSBSensorGyroData *GyroData, NSError *error) {
                NSLog(@&#34;Starting updates&#34;);
                self.currentGyroLabel.text = ;
            }];
      } else {
            NSLog(@&#34;Error connecting: %@&#34;, error);
      }
    }];
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何阻止代码等待连接,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/29572544/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/29572544/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何阻止代码等待连接