PromiseKit/swiftを読んだ

2014-08-13#swift

PromiseKitとは

使い方

NSURLConnection.GET("http://placekitten.com/250/250").then{ (img:UIImage) in
    // ...
    return CLGeocoder.geocode(addressString:"Mount Rushmore")
}.then { (placemark:CLPlacemark) in
    // ...
    return MKMapSnapshotter(options:opts).promise()
}.then { (snapshot:MKMapSnapshot) -> Promise<Int> in
    // ...
    let av = UIAlertView()
    // ...
    return av.promise()
}.then {
    self.title = "You tapped button #\($0)"
}.then {
    return CLLocationManager.promise()
}.catch { _ -> CLLocation in
    return CLLocation(latitude: 41.89, longitude: -87.63)
}.then { (ll:CLLocation) -> Promise<NSDictionary> in
    // ...
}.then
// ...

tl;dr


NSURLConnection+Promise.swift

public class func GET(url:String) -> Promise<NSData> {
    // ...
}
public class func GET(url:String) -> Promise<UIImage> {
    let rq = NSURLRequest(URL:NSURL(string:url))
    return promise(rq)
}
public class func promise(rq:NSURLRequest) -> Promise<UIImage> {
    return fetch(rq) { (fulfiller, rejecter, data) in
        // ...
    }
}
func fetch<T>(var request: NSURLRequest, body: ((T) -> Void, (NSError) -> Void, NSData) -> Void) -> Promise<T> {
    // ...

    return Promise<T> { (fulfiller, rejunker) in
        // ...
    }
}
// Promise.swift

public init(_ body:(fulfiller:(T) -> Void, rejecter:(NSError) -> Void) -> Void) {
    // ...
    body(fulfiller, rejecter)
}
// Promise.swift

public init(_ body:(fulfiller:(T) -> Void, rejecter:(NSError) -> Void) -> Void) {
    func recurse() {
        for handler in handlers { handler() }
        handlers.removeAll(keepCapacity: false)
    }
    func rejecter(err: NSError) {
        if self.pending {
            self.state = .Rejected(err)
            recurse()
        }
    }
    func fulfiller(obj: T) {
        if self.pending {
            self.state = .Fulfilled(obj)
            recurse()
        }
    }

    body(fulfiller, rejecter)
}
func fetch<T>(var request: NSURLRequest, body: ((T) -> Void, (NSError) -> Void, NSData) -> Void) -> Promise<T> {
    // ...

    return Promise<T> { (fulfiller, rejunker) in
        NSURLConnection.sendAsynchronousRequest(request, queue:PMKOperationQueue) { (rsp, data, err) in
            // ...

            if err {
                rejecter(err)
            } else {
                body(fulfiller, rejecter, data!)
            }
        }
    }
}

Promise.swift

public func then<U>(onQueue q:dispatch_queue_t = dispatch_get_main_queue(), body:(T) -> U) -> Promise<U> {
}
public func then<U>(onQueue q:dispatch_queue_t = dispatch_get_main_queue(), body:(T) -> U) -> Promise<U> {
    switch state {
    case .Rejected(let error):
        // ...
    case .Fulfilled(let value):
        // ...
    case .Pending:
        // ...
    }
}
enum State<T> {
    case Pending
    case Fulfilled(@autoclosure () -> T)
    case Rejected(NSError)
}
public func then<U>(onQueue q:dispatch_queue_t = dispatch_get_main_queue(), body:(T) -> U) -> Promise<U> {
    switch state {
    case .Rejected(let error):
        // ...
    case .Fulfilled(let value):
        // ...
    case .Pending:
        // ...
    }
}
public func then<U>(onQueue q:dispatch_queue_t = dispatch_get_main_queue(), body:(T) -> U) -> Promise<U> {
    switch state {
    // ...
    case .Pending:
        return Promise<U>{ (fulfiller, rejecter) in
            // ...
        }
    }
}
public func then<U>(onQueue q:dispatch_queue_t = dispatch_get_main_queue(), body:(T) -> U) -> Promise<U> {
    switch state {
    // ...
    case .Pending:
        return Promise<U>{ (fulfiller, rejecter) in
            self.handlers.append{
                switch self.state {
                case .Fulfilled(let value):
                    fulfiller(value())
                case .Rejected(let error):
                    dispatch_async(onQueue){ fulfiller(body(error)) }
                case .Pending:
                    abort()
                }
            }
        }
    }
}