Synchronizing Async Stuff in Swift

1.3k views Asked by At

I'm not sure why Apple designs so many things in blocks... At least the problem in "PHAsset to UIImage" was able to be resolved due to a provided option. However, some of the other things I need are not provided by options.

For example:

func getAssetUrl(asset: PHAsset) -> NSURL {
    var option = PHContentEditingInputRequestOptions()
    asset.requestContentEditingInputWithOptions(option, completionHandler: {(contentEditingInput, info) -> Void in
            var imageURL = contentEditingInput.fullSizeImageURL
        println(imageURL)
        })
    return NSURL()
}

In these cases, I just want functions that take a block (such as requestContentEditingInputWithOptions to synchronically execute so I can return the imageURL). Is there any way to do this? (I've tried using some dispatch commands, but have not reached success yet).

Please note that I NEED to return the imageURL. Do not attempt to give me a solution in which I write stuff inside the block and don't return the imageURL.

1

There are 1 answers

1
Rob On

I know you explicitly asked not to see this answer, but for the sake of future readers, I feel compelled to post the correct way to handle asynchronous methods, namely follow asynchronous patterns yourself and employ a completionHandler:

func getAssetUrl(asset: PHAsset, completionHandler: @escaping (URL?) -> Void) {
    let option = PHContentEditingInputRequestOptions()
    asset.requestContentEditingInput(with: option) { contentEditingInput, _ in
        completionHandler(contentEditingInput?.fullSizeImageURL)
    }
}

And you'd use it like so:

getAssetUrl(asset) { url in
    guard let url = url else { return }

    // do something with URL here
}

// anything that was here that needs URL now goes above, inside the `completionHandler` closure

There are other, more complicated patterns (operations, third-party promises/futures implementations, etc.), but the completionHandler pattern generally handles these situations quite gracefully.