Search code examples
swiftcallbackwaitapple-watch

Swift How to wait for callback to finish before exiting function?


The problem I'm having on this request is the first function syncRequest always returns nil since the function exits before the (reply, error) comes back to fill out my return dictionary.

Is there a way for it to wait for the callback to return before returning out of my closure?

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)
        }
    }
}

Your help us much appreciated!


Solution

  • Could you have syncRequest() take a closure that gets called with the results when ready? Change the definition to something like:

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

    Then at the end of your createRequest() call, you could call the callback on syncResponseDict, since now it's been populated with your data... callback(syncResponseDict).

    EDIT: Here's the solution I had in mind.

    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)
            }
        }()
    }