Group Group Group Group Group Group Group Group Group
raywenderlich.com Forums

Getting Started with PromiseKit

Asynchronous programming can be a real pain in the lemon. Unless you’re extremely careful, it can easily result in humongous delegates, messy completion handlers and long nights debugging code! Lucky for you, there’s a better way: promises. Promises tame asynchronicity by letting you write code as a series of actions based on events. This works […]


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/786-getting-started-with-promisekit

How does URLDataPromise ensure that asDictionary() is not called until it completes?

//1
let dataPromise: URLDataPromise = session.dataTask(with: request)

// 2
_ = dataPromise.asDictionary().then { dictionary -> Void in

.asDictinary() probably doesn’t actually do anything other than register for something to happen later, when the data does arrive.

For example, this hastily written skeleton of something vaguely Promise-ish:

struct Xyz {}

class Promise {

    var transformFunc: ((Any) -> Any)?;
    var data: Any?;

    static func promiseFetchingData(fromUrl url: String) -> Promise {
        let p = Promise()
        p.getData(fromUrl: url)
        return p
    }

    func getData(fromUrl url: String) {
        // Make http request, store result in self.data, or pass to transform and .then, if already available
    }

    func asDictionary() -> Promise {
        transformFunc = transformToDictionary
        return self
    }

    func asXyz() -> Promise {
        transformFunc = transformToXyz
        return self
    }

    func then(handler: (Any) -> ()) {
        if let t = transformFunc {
            data = t(data)
        }
        handler(data)
    }

    func transformToDictionary(data: Any) -> Dictionary<String,Any> {
        return ["key": 1234, "other": 5678]
    }

    func transformToXyz(data: Any) -> Xyz {
        return Xyz()
    }

}

_ = Promise.promiseFetchingData(fromUrl: "http://myserver.net/api/1234" )
            .asDictionary()
            .then {
                dict in
                // Do stuff
                print(dict)
            }

Real code would need to allow for data returning before the transformation or the .then() were registered.

A (good) while ago I made my own bare bone and easy-to-use Promise class for Swift: Swift Promises (Github)
Updated every so slightly here and there since the Swift 2 days to accommodate for the language’s changes.

Fair warning, it is really bare bones. But I’ve been using it for practically all of the iOS apps I’ve worked on in the past 12+ months and has served me really well for async related tasks.

It was interesting how developers were already creating their own Promise libraries for Swift since the beta days. Both PromiseKit and BrightFutures are the names I’ve seen pop-up most over the years. And I’m glad your article has gone in-depth with one of them. It certainly convinced me to give it a try next time. (Or maybe help me improve my own simple Promise class. :slight_smile: ) Cheers!

@frzi

One nice thing about all these open source libraries is that you can always pick and choose parts of it to upgrade your own implementation as the need arises.

@mkatz I downloaded the sample project and found that it keeps showing an warning – “This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.”(iOS Deployment Target 10.0 & Xcode 8.3.3).

I think you probably should fix this by putting the > completion(result, nil) within DispatchQueue.main.async { … } in function getWeatherTheOldFashionedWay(latitude:, longitude:, completion:).

Thanks, what a boneheaded move! We’ll get that on the next update round.

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]