在返回值之前等待委托执行

Posted

技术标签:

【中文标题】在返回值之前等待委托执行【英文标题】: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,您会注意到完成处理程序无法解决问题 【参考方案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)
     

【讨论】:

以上是关于在返回值之前等待委托执行的主要内容,如果未能解决你的问题,请参考以下文章

如何在返回值之前等待关闭完成

UITextView shouldInteractWith 委托在警报完成中返回值

如何使用事件发射器调用返回值的函数,并在继续之前等待响应?

按值返回值而不等待所有值返回异步 C#

C# Action用法

C#委托初学