【问题标题】:Swift How to wait for callback to finish before exiting function?Swift 如何在退出函数之前等待回调完成?
【发布时间】:2015-01-27 04:05:53
【问题描述】:

我在这个请求上遇到的问题是第一个函数 syncRequest 总是返回 nil,因为函数在 (reply, error) 返回填写我的返回字典之前退出。

有没有办法让它在退出我的关闭之前等待回调返回?

public typealias KKWatchSyncResponse = Dictionary<String, AnyObject>

func syncRequest() -> KKWatchSyncResponse? {
    var syncResponseDict : KKWatchSyncResponse?
    createRequest(KKWatchRequest.Sync, parameter: nil) { reply, error in
        if reply == nil || error != nil {
            return
        } else {
            syncResponseDict = KKWatchSyncResponse()
        }
        if let songInfo = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["songInfo"] as NSData) as NSDictionary? {
            syncResponseDict!["songInfo"] = songInfo
        }
        if let albumArtImage = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["albumArt"] as NSData) as? UIImage {
            syncResponseDict!["albumArtImage"] = albumArtImage
        }
        if let isPlaying = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["isPlaying"] as NSData) as? Bool {
            syncResponseDict!["isPlaying"] = isPlaying
        }
    }()
    return syncResponseDict
}

    func createRequest(request:KKWatchRequest, parameter: KKWatchAPIRequestParameter?, callback:KKWatchAPICallback) -> KKWatchAPIParentRequest {
       var requestDict : Dictionary<String, AnyObject> = [KKBOXWatchAppRequestType : request.rawValue]
        if parameter != nil {
        requestDict += parameter! //Combine 2 dictionaries
    }
        return { WKInterfaceController.openParentApplication(requestDict){ reply, error in
                callback(reply, error)
        }
    }
}

非常感谢您对我们的帮助!

【问题讨论】:

    标签: swift callback wait apple-watch


    【解决方案1】:

    你能不能让syncRequest() 使用一个闭包,并在准备好后调用结果?将定义更改为:

    func syncRequest(callback:(KKWatchSyncResponse?)->Void) { ... }
    

    然后在您的createRequest() 调用结束时,您可以在syncResponseDict 上调用回调,因为现在它已经填充了您的数据...callback(syncResponseDict)

    编辑:这是我想到的解决方案。

    func syncRequest(callback:(KKWatchSyncResponse?)->Void) {
        createRequest(KKWatchRequest.Sync, parameter: nil) { reply, error in            
            if reply == nil || error != nil {
                callback(nil)
            } else {
                var syncResponseDict : KKWatchSyncResponse? = KKWatchSyncResponse()
                if let songInfo = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["songInfo"] as NSData) as NSDictionary? {
                    syncResponseDict!["songInfo"] = songInfo
                }
                if let albumArtImage = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["albumArt"] as NSData) as? UIImage {
                    syncResponseDict!["albumArtImage"] = albumArtImage
                }
                if let isPlaying = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["isPlaying"] as NSData) as? Bool {
                    syncResponseDict!["isPlaying"] = isPlaying
                }
                callback(syncResponseDict)
            }
        }()
    }
    

    【讨论】:

    • 是的!这正是我正在寻找的。谢谢楼主:)
    • 太棒了。没问题...很高兴它有帮助。
    【解决方案2】:

    实现锁定变量很简单。这对于执行一些异步网络加载的单元测试最有帮助。

    func waitingFunction()
    {
         //set a lock during your async function
         var locked = true
         RunSome.asyncFunction() { () -> Void in
    
           //after your sync function remove the lock
           locked = false
         })
    
         //wait for the async method to complete before advancing
         while(locked){wait()}
    
         //move on from the lock
         doMoreStuff()
    }
    func wait()
    {
        NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 1))
    }
    

    【讨论】:

    • 我不鼓励使用这种模式:在没有同步的情况下访问不同线程上的变量(此处为 locked)不是线程安全的。在这里,它恰好在强排序 CPU(英特尔)上工作,但在 ARM 上可能会失败。对于单元测试,我们在 XCTest 中提供了一种稳健的方法,并专门针对此用例制定了预期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 2022-12-18
    • 1970-01-01
    • 2021-12-02
    相关资源
    最近更新 更多