现代编程语言都很好的支持了异步编程,因此在 swift 编程中,拥有功能强大且轻量级的异步编程工具的需求变得很强烈。
UIApplication.shared.isNetworkActivityIndicatorVisible = true
firstly {
when(URLSession.dataTask(with: url).asImage(), CLLocationManager.promise())
}.then { image, location -> Void in
self.imageView.image = image;
self.label.text = "\(location)"
}.always {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}.catch { error in
UIAlertView(/*…*/).show()
}
PromiseKit 是一款 swift 编写的支持 iOS,macOS,tvOS,watchOS 等多平台的轻量级异步编程库,同时 PromiseKit 完美的支持了 Objective-C 桥接。
我们推荐您使用 CocoaPods 或者 Carthage 来集成 PromiseKit,您也可以通过把 PromiseKit.xcodeproj
拖拽到项目中并导入 PromiseKit.framework
来手动集成。
# CocoaPods >= 1.1.0-rc.2
swift_version = "3.0"
pod "PromiseKit", "~> 4.0"
# Carthage
github "mxcl/PromiseKit" ~> 4.0
# SwiftPM
let package = Package(
dependencies: [
.Package(url: "https://github.com/mxcl/PromiseKit", majorVersion: 4)
]
)
# CocoaPods
swift_version = "2.3"
pod "PromiseKit", "~> 3.5"
# Carthage
github "mxcl/PromiseKit" ~> 3.5
您可以通过 promisekit.org 站点来查看全部文档
在 then
方法中定义异步任务:
login().then { json in
//…
}
链式调用:
login().then { json -> Promise<UIImage> in
return fetchAvatar(json["username"])
}.then { avatarImage in
self.imageView.image = avatarImage
}
catch
链式调用进行错误处理:
login().then {
return fetchAvatar()
}.then { avatarImage in
//…
}.catch { error in
UIAlertView(/*…*/).show()
}
组合调用:
let username = login().then{ $0["username"] }
when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}.then { image in
//…
}
简单重构:
func avatar() -> Promise<UIImage> {
let username = login().then{ $0["username"] }
return when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}
}
您也可以创建一个新的异步任务:
func fetchAvatar(user: String) -> Promise<UIImage> {
return Promise { fulfill, reject in
MyWebHelper.GET("\(user)/avatar") { data, err in
guard let data = data else { return reject(err) }
guard let img = UIImage(data: data) else { return reject(MyError.InvalidImage) }
guard let img.size.width > 0 else { return reject(MyError.ImageTooSmall) }
fulfill(img)
}
}
}
您可以通过 promisekit.org 站点获得更多用法。
由于 Xcode 支持不同版本的 swift,下面是 PromiseKit 与 Xcode 的对应关系:
Swift | Xcode | PromiseKit | CI Status | Release Notes |
---|---|---|---|---|
3 | 8 | 4 | 2016/09 | |
2 | 7/8 | 3 | 2015/10 | |
1 | 7 | 3 | – | 2015/10 |
N/A | * | 1† | – |
† PromiseKit 1 是纯 Objective-C 开发的,因此您可以在 Xcode 的任何版本中使用,当需要支持 iOS 7 或更低版本时只能选择 PromiseKit 1。
我们同时维护了一些分支来帮助您做 Swift 版本间的移植:
Xcode | Swift | PromiseKit | Branch | CI Status |
---|---|---|---|---|
8.0 | 2.3 | 2 | swift-2.3-minimal-changes | |
7.3 | 2.2 | 2 | swift-2.2-minimal-changes | |
7.2 | 2.2 | 2 | swift-2.2-minimal-changes | |
7.1 | 2.1 | 2 | swift-2.0-minimal-changes | |
7.0 | 2.0 | 2 | swift-2.0-minimal-changes |
我们通常不会再对这些分支做维护,但同样欢迎提交 PR。
Promises 仅在执行异步任务时非常有用,因此我们把苹果绝大部分接口都转换成了异步任务。当导入 Promises 时已经默认包含了 UIKit 和 Foundation。其他框架需要在 Podfile
中单独声明:
pod "PromiseKit/MapKit" # MKDirections().promise().then { /*…*/ }
pod "PromiseKit/CoreLocation" # CLLocationManager.promise().then { /*…*/ }
扩展的所有 repo 请访问 PromiseKit org 。
在 Cartfile
中声明:
github "PromiseKit/MapKit" ~> 1.0
直接使用 URLSession
通常是不可取的,您可以选择使用 Alamofire or OMGHTTPURLRQ:
// pod 'PromiseKit/Alamofire'
Alamofire.request("http://example.com", withMethod: .GET).responseJSON().then { json in
//…
}.catch { error in
//…
}
// pod 'PromiseKit/OMGHTTPURLRQ'
URLSession.GET("http://example.com").asDictionary().then { json in
}.catch { error in
//…
}
AFNetworking 我们推荐使用 csotiriou/AFNetworking。
如果您有任何问题可以访问 Gitter chat channel,也可以进行 bug 追踪