【问题标题】:Wait for delegate execution before returning value在返回值之前等待委托执行
【发布时间】:2016-02-17 20:29:44
【问题描述】:

我有一些带有 getter 和 setter 的类属性,它们向设备发送一些命令以设置或获取一些值。 CoreBluetooth 是异步工作的,例如,在返回值之前,我必须检查设备是否已响应命令,检查响应有效性,然后将值返回给调用者。

只是为了有个清晰的想法……

class A: Delegate {
    func peripheral(
        peripheral: CBPeripheral,
        didUpdateValueForCharacteristic characteristic: CBCharacteristic,
        error: NSError?)
    {
        // receive some data, parse it and assign to lastResponse
        A.lastResponse = ...
    } 

}

class A {
    static var lastResponse: SomeObject?

    // get or set device name
    static var name: String {
        get {
            // send command to device
            ...

            // wait until a response is received
            ...

            return lastResponse.value
        }
        set {
            // same as getter but have to ensure that the command
            // has been received from device by checking the response code
        }
    }
}

我的想法是使用 NSCondition 对象等到条件变为真,但可能会冻结 UI。目标是等待异步函数/委托从同步函数执行而不冻结。

你知道怎么解决吗?

【问题讨论】:

  • 不要等待。处理它是异步的事实。使用委托、回调闭包或 NSNotification
  • 在委托中使用委托似乎不是一种更清洁的方式。完成处理程序被同步调用。可能 NSNotification 可能是问题解决者
  • 我的选择可能是完成处理程序,但 NSNotification 也可以工作
  • 好吧,你不能真正使用属性获取器,因为你的底层数据源是异步的。这取决于值是否可以通过 Bkuetooth 通知异步更新,以及是否有多个观察者想同时了解值的变化。在这些情况下,您将使用 NSNotification。如果只有一个观察者想要该值并且他们必须从设备请求该值,那么您可以将完成处理程序存储在由特征键控的字典中,发出读取,然后在读取完成时调用存储的完成处理程序
  • 如果可能,完成处理程序将是一个完美的解决方案,但假设此代码为gist.github.com/luciocorsa/15c0862c129dd9c5ae74,您会注意到完成处理程序无法解决问题

标签: ios swift


【解决方案1】:

一种可能的方法是不将 name 作为属性访问,而是编写一个方法调用来请求 name 并期望对它的委托调用,并在此委托调用中做任何你需要做的事情。

class protocol Delegate {
    func deviceName(name: String);
}

class A: Delegate {
        func peripheral(
            peripheral: CBPeripheral,
            didUpdateValueForCharacteristic characteristic: CBCharacteristic,
            error: NSError?)
        {
            // receive some data, parse it and assign to lastResponse
            A.lastResponse = ...
            A.delegate = self
            A.requestName()
        } 

        func deviceName(name: String) {
          //do what u wish with the name
        }

    }

    class A {
        static var lastResponse: SomeObject?
        var delegate: Delegate?

        // get or set device name
        static var name: String?


    func requestName() {
         ...
         // send command to device
         ...

         // when a response is received
         ...
         name = //name received
         delegate.deviceName(name)
     }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多