現今的程式開發大量使用非同步存取, 難道不正是時候該開始考慮使用合適的工具讓非同步程式更加的強大, 易用, 並且使用愉快?
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 語言完整實作 Promise 概念的工具套件. 除了能夠完美的和現有的 Objective-C 程式進行整合之外, 也支援多個不同平台, 如, iOS, macOS, tvOs 以及 watchOS.
我們推薦使用 CocoaPods 或 Carthage 等套件管理程式來進行安裝. 如不使用套件管理程式安裝, 也可以手動下載相關程式, 並把 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
}
串連式的錯誤/例外處理:
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 學習更多完整的用法.
PromiseKit 使用 Swift 進行開發, 下表列出 Xcode 以及 Swifit 的相關對應版本:
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 版本中使用,若您需要支援 iOS7 或者更低版本時, 只能選擇使用 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 僅對執行非同步任務非常有用, 因此我們把 Apple 絕大部份的 API 轉換成 Promises. 透過 CocoaPod 導入套件時即預設帶入 UIKit 和 Foundation, 而其他框架需要在您的 Podfile
檔案中進行額外的設定, 例如:
pod "PromiseKit/MapKit" # MKDirections().promise().then { /*…*/ }
pod "PromiseKit/CoreLocation" # CLLocationManager.promise().then { /*…*/ }
我們所有相關的擴充專案可以到 PromiseKit org 查詢.
使用 Cartfile
進行設定:
github "PromiseKit/MapKit" ~> 1.0
NSURLSession
一般來說很難勝任複雜的網路存取相關任務; 建議使用 Alamofire 或者 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.
與我聯繫, 我在 iOS 上使用 Promises 進行開發已經有多年的經驗, 同時也有 10 年以上開發行動裝置 App 的經驗.
可以在 Gitter chat channel 詢問相關問題, 或者直接追蹤我們的 bug tracker