【问题标题】:Swift: escaping a closure based on external boolean?Swift:基于外部布尔值转义闭包?
【发布时间】:2022-08-21 17:57:41
【问题描述】:

我的应用程序需要通过 Siri 快捷方式意图连接并写入蓝牙设备。一旦调用 IntentHandling 类中的完成处理程序,连接过程就会终止。

蓝牙处理包含在一个名为 BTHandler 的单例中。写入响应由 BTHandler 调用的委托函数确认。这是委托函数的代码和处理意图的简化函数:

var writeCompleted = false

//delegate function
func writeConfirmed() {
    writeCompleted = true
}


func handle(intent: SwitchIntent, completion: @escaping (SwitchIntentResponse) -> Void) {
    
    BTHandler.shared.responseDelegate = self    

    BTHandler.shared.scan {
    
        BTHandler.shared.centralManager.stopScan()     
        BTHandler.shared.write(btdevice: BTHandler.shared.discoveredDevice, command: .write)   
        
        completion(SwitchIntentResponse(code: .success, userActivity: nil))
    }

}

只有当 writeCompleted 为真时,才有办法调用完成?

  • 您的问题的标题和正文不匹配。 \"只有当 writeCompleted 为真时,是否有方法调用完成?\" 当然,if writeCompleted { completion(...) }。 \"基于外部布尔值转义闭包?\" 这是不可能的,因为@escaping 是一种修改调用者如何将闭包传递给您的函数的效果。如果它可以转义,则它有一组需要强制执行的规则,并且通常需要将更多的东西移动到堆中。它不知道是否真的发生了逃逸,所以它总是需要表现得好像它是可能的一样
  • guard self.writeCompleted else { return } 作为完成处理程序的第一行怎么样?当然在所有情况下都会调用它,但它不会做任何事情

标签: swift closures shortcut siri


【解决方案1】:

我添加了一个计时器来检查writeCompleted 是否为真。这也允许在writeCompleted 永远不会改变的情况下设置超时值。

现在在后台进行 BT 扫描还有另一个问题,但这是题外话。

func handle(intent: SwitchIntent, completion: @escaping (SwitchIntentResponse) -> Void) {
    
    BTHandler.shared.responseDelegate = self    

    BTHandler.shared.scan {
    
        BTHandler.shared.centralManager.stopScan()     
        BTHandler.shared.write(btdevice: BTHandler.shared.discoveredDevice, command: .write)   
        
        var timeoutCounter = 0.0
            
            Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { timer in
                
                timeoutCounter += timer.timeInterval

                if self.writeCompleted   {
                    timer.invalidate()
                    completion(SwitchIntentResponse(code: .success, userActivity: nil))
                    
                }
                
                if timeoutCounter == 3.0 {
                    timer.invalidate()
                    completion(SwitchIntentResponse(code: .timeout, userActivity: nil))
                }
                
            }
    }

}

【讨论】:

  • 可怕的设计。不要在任何不是 UI 的东西上使用计时器。不要用时间来衡量某事是否完成。解决问题,不要用计时器/睡眠等来帮助他们
  • 你是绝对正确的!我已经用一个观察者替换了我的代码,该观察者在 writeCompleted 为真时通知 IntentHandling 类。
猜你喜欢
  • 2021-12-14
  • 2019-04-14
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 2014-01-17
  • 2015-12-21
相关资源
最近更新 更多