Compare commits

...

11 Commits

Author SHA1 Message Date
Max Howell
47f40ef75f
Update docs, fix broken links
Removes Chinese translations because they were far behind.

[ci skip]
2019-02-28 23:37:10 -05:00
Max Howell
dd77da78cb Test against Xcode 10.1 2018-12-27 09:55:29 +00:00
Max Howell
1001d23725 Test everything we claim to support 2018-06-04 19:30:20 -04:00
Max Howell
a92c40ca73 Update docs for Xcode 10 2018-06-04 19:25:02 -04:00
Max Howell
7fb12976da Fix Swift 4.2 warnings 2018-06-04 19:23:16 -04:00
Max Howell
99771a775e Update xcodeproj to Xcode 10 2018-06-04 19:23:02 -04:00
Max Howell
c70677a12b Update StoreKit extension; Tag 4.5.2 2018-01-29 11:06:23 -05:00
Max Howell
de638abca5 Update extensions; Tag 4.5.1 2018-01-05 18:17:35 -05:00
Max Howell
52697b25d4 Provide localizedDescription errors 2017-12-04 10:59:37 -05:00
Max Howell
6bab5e0c7f Add @discardableResult; Closes #595; Tag 4.5.0
PromiseKit 5 much improves this area with the concept of an unavailable promise (`Guarantee`).

Thus since we offer a superior library now, we will close this ticket.
2017-11-05 17:52:08 -05:00
Max Howell
d7a978d628 Update CoreLocation 2017-11-05 17:16:49 -05:00
19 changed files with 187 additions and 505 deletions

View File

@ -1,5 +1,90 @@
matrix:
include:
- os: osx
language: objective-c
osx_image: xcode10.1
env: SWFT=4.2 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode10.1
env: SWFT=4.2 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode10.1
env: SWFT=4.2 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode10.1
env: SWFT=4.2 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=4.1 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=4.1 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=4.1 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=4.1 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=3.2 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=3.2 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=3.2 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.3
env: SWFT=3.2 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=4.0 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=4.0 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=4.0 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=4.0 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=3.2 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=3.2 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=3.2 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.2
env: SWFT=3.2 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.1
@ -34,6 +119,40 @@ matrix:
osx_image: xcode9.1
env: SWFT=3.2 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=4.0 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=4.0 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=4.0 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=4.0 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=3.2 PLAT=macOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=3.2 PLAT=iOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=3.2 PLAT=tvOS
- os: osx
language: objective-c
osx_image: xcode9.0
env: SWFT=3.2 PLAT=watchOS
- os: osx
language: objective-c
osx_image: xcode8.3

View File

@ -342,7 +342,7 @@ is more thorough at the source.
In Xcode dont forget to `⌥` click on PromiseKit functions to get at this
documentation while you are developing.
Otherwise return to our [contents page](/Documentation).
Otherwise return to our [contents page](..).
[sources]: https://github.com/mxcl/PromiseKit/tree/master/Sources

View File

@ -1,4 +1,4 @@
# Xcode 8 or 9 / Swift 3 or 4
# Xcode 8, 9 or 10 / Swift 3 or 4
We recommend CocoaPods.
@ -46,8 +46,7 @@ PromiseKit contains Swift, so there have been rev-lock issues with Xcode:
| PromiseKit | Swift | Xcode | CI Status | Release Notes |
| ---------- | -------- | -------- | ------------ | ----------------- |
| 5 | 3.x, 4.x | 8.x, 9.x | ![ci-master] | In beta |
| 4 | 3.x, 4.x | 8.x, 9.x | ![ci-master] | [2016/09][news-4] |
| 4 | 3.x, 4.x | 8.x, 9.x, 10.1 | ![ci-master] | [2016/09][news-4] |
| 3 | 2.x | 7.x, 8.0 | ![ci-swift2] | [2015/10][news-3] |
| 2 | 1.x | 7.x | Unsupported | [2015/10][news-3] |
| 1† | *N/A* | * | ![ci-legacy] | |
@ -82,12 +81,6 @@ pod "PromiseKit", "~> 3.5"
github "mxcl/PromiseKit" ~> 3.5
```
# PromiseKit 5
[PromiseKit 5 is experimental and under active development](https://github.com/mxcl/PromiseKit/tree/experimental-5.x).
[travis]: https://travis-ci.org/mxcl/PromiseKit
[ci-master]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=master
[ci-legacy]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=legacy-1.x
@ -96,7 +89,7 @@ github "mxcl/PromiseKit" ~> 3.5
[ci-22]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.2-minimal-changes
[ci-20]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.0-minimal-changes
[news-2]: http://promisekit.org/news/2015/05/PromiseKit-2.0-Released/
[news-3]: https://github.com/mxcl/PromiseKit/blob/master/CHANGELOG.markdown#300-oct-1st-2015
[news-3]: https://github.com/mxcl/PromiseKit/blob/212f31f41864d1e3ec54f5dd529bd8e1e5697024/CHANGELOG.markdown#300-oct-1st-2015
[news-4]: http://promisekit.org/news/2016/09/PromiseKit-4.0-Released/
[swift-2.3-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.3-minimal-changes
[swift-2.2-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.2-minimal-changes

View File

@ -1,6 +1,6 @@
# Contents
* [README](/README.md)
* [README](../README.md)
* Handbook
* [Getting Started](GettingStarted.md)
* [Promises: Common Patterns](CommonPatterns.md)

@ -1 +1 @@
Subproject commit 2d9497395350fd0219ba7b62ac08b55f0d2c7cdb
Subproject commit 5636e88018ee9cfcea68bccd39f74409c1faea53

@ -1 +1 @@
Subproject commit 111d2b4fedd8729c2bb9deabc04b03bb1f47dcdb
Subproject commit ac0e2140d57c0193222582872586bf3ff30cc634

@ -1 +1 @@
Subproject commit a56c183961d1bfe368df40804544b968eb84e0f9
Subproject commit 0e1d5981ebfb495062cc61368edb2d46e8831cf5

View File

@ -509,7 +509,7 @@
6399A3721D595D9100D65233 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0900;
LastUpgradeCheck = 1000;
TargetAttributes = {
630019011D596292003B4E30 = {
LastSwiftMigration = 0900;
@ -773,12 +773,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@ -787,7 +789,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 4.4.4;
CURRENT_PROJECT_VERSION = 4.5.2;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@ -831,12 +833,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@ -845,7 +849,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 4.4.4;
CURRENT_PROJECT_VERSION = 4.5.2;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "1000"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -96,7 +95,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@ -1,8 +1,6 @@
![PromiseKit](http://promisekit.org/public/img/logo-tight.png)
![PromiseKit](../gh-pages/public/img/logo-tight.png)
![badge-pod] ![badge-languages] ![badge-pms] ![badge-platforms] [![Build Status](https://travis-ci.org/mxcl/PromiseKit.svg?branch=master)](https://travis-ci.org/mxcl/PromiseKit)
[繁體中文](README.zh_Hant.md), [简体中文](README.zh_CN.md)
![badge-pod][] ![badge-languages][] ![badge-pms][] ![badge-platforms][] [![Build Status](https://travis-ci.org/mxcl/PromiseKit.svg?branch=master)](https://travis-ci.org/mxcl/PromiseKit)
---
@ -41,7 +39,7 @@ target "Change Me!" do
end
```
PromiseKit 4 supports Xcode 8.1, 8.2, 8.3 and 9.0; Swift 3.0, 3.1, 3.2 and 4.0; iOS, macOS, tvOS, watchOS, Linux and Android; CocoaPods, Carthage and SwiftPM; ([CI Matrix](https://travis-ci.org/mxcl/PromiseKit)).
PromiseKit 4 supports Xcode 8.1, 8.2, 8.3, 9.0, 9.1, 9.2, 10.0 and 10.1; Swift 3.0, 3.1, 3.3, 4.0, 4.1 and 4.2; iOS, macOS, tvOS, watchOS, Linux and Android; CocoaPods, Carthage and SwiftPM; ([CI Matrix](https://travis-ci.org/mxcl/PromiseKit)).
For Carthage, SwiftPM, etc., or for instructions when using older Swifts or
Xcodes see our [Installation Guide](Documentation/Installation.md).

View File

@ -1,238 +0,0 @@
![PromiseKit](http://promisekit.org/public/img/logo-tight.png)
![badge-pod] ![badge-languages] ![badge-pms] ![badge-platforms] ![badge-mit]
[English](README.markdown)
---
现代编程语言都很好的支持了异步编程,因此在 swift 编程中,拥有功能强大且轻量级的异步编程工具的需求变得很强烈。
```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 编写的支持 iOSmacOStvOSwatchOS 等多平台的轻量级异步编程库,同时 PromiseKit 完美的支持了 Objective-C 桥接。
# 快速预览
我们推荐您使用 [CocoaPods] 或者 [Carthage] 来集成 PromiseKit您也可以通过把 `PromiseKit.xcodeproj` 拖拽到项目中并导入 `PromiseKit.framework` 来手动集成。
## Xcode 8 / Swift 3
```ruby
# 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)
]
)
```
## Xcode 8 / Swift 2.3 or Xcode 7
```ruby
# CocoaPods
swift_version = "2.3"
pod "PromiseKit", "~> 3.5"
# Carthage
github "mxcl/PromiseKit" ~> 3.5
```
# 文档
您可以通过 [promisekit.org] 站点来查看全部文档
## 概览
`then` 方法中定义异步任务:
```swift
login().then { json in
//…
}
```
链式调用:
```swift
login().then { json -> Promise<UIImage> in
return fetchAvatar(json["username"])
}.then { avatarImage in
self.imageView.image = avatarImage
}
```
`catch` 链式调用进行错误处理:
```swift
login().then {
return fetchAvatar()
}.then { avatarImage in
//…
}.catch { error in
UIAlertView(/*…*/).show()
}
```
组合调用:
```swift
let username = login().then{ $0["username"] }
when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}.then { image in
//…
}
```
简单重构:
```swift
func avatar() -> Promise<UIImage> {
let username = login().then{ $0["username"] }
return when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}
}
```
您也可以创建一个新的异步任务:
```swift
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 vs. Xcode
由于 Xcode 支持不同版本的 swift下面是 PromiseKit 与 Xcode 的对应关系:
| Swift | Xcode | PromiseKit | CI Status | Release Notes |
| ----- | ----- | ---------- | ------------ | ----------------- |
| 3 | 8 | 4 | ![ci-master] | [2016/09][news-4] |
| 2 | 7/8 | 3 | ![ci-swift2] | [2015/10][news-3] |
| 1 | 7 | 3 | | [2015/10][news-3] |
| *N/A* | * | 1† | ![ci-legacy] | |
† 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] | ![ci-23] |
| 7.3 | 2.2 | 2 | [swift-2.2-minimal-changes] | ![ci-22] |
| 7.2 | 2.2 | 2 | [swift-2.2-minimal-changes] | ![ci-22] |
| 7.1 | 2.1 | 2 | [swift-2.0-minimal-changes] | ![ci-20] |
| 7.0 | 2.0 | 2 | [swift-2.0-minimal-changes] | ![ci-20] |
我们通常不会再对这些分支做维护,但同样欢迎提交 PR。
# 扩展
Promises 仅在执行异步任务时非常有用,因此我们把苹果绝大部分接口都转换成了异步任务。当导入 Promises 时已经默认包含了 UIKit 和 Foundation。其他框架需要在 `Podfile` 中单独声明:
```ruby
pod "PromiseKit/MapKit" # MKDirections().promise().then { /*…*/ }
pod "PromiseKit/CoreLocation" # CLLocationManager.promise().then { /*…*/ }
```
扩展的所有 repo 请访问 [PromiseKit org ](https://github.com/PromiseKit)。
`Cartfile` 中声明:
```ruby
github "PromiseKit/MapKit" ~> 1.0
```
## 选择网络库
直接使用 `URLSession` 通常是不可取的,您可以选择使用 [Alamofire] or [OMGHTTPURLRQ]:
```swift
// 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]。
# 需要将您的代码转换到 Promises?
[有偿帮助](mailto:mxcl@me.com),我有几年 Promises 编码经验并在移动开发领域已有 10 年的开发经验。
# 支持
如果您有任何问题可以访问 [Gitter chat channel](https://gitter.im/mxcl/PromiseKit),也可以进行 [bug 追踪](https://github.com/mxcl/PromiseKit/issues/new)
[travis]: https://travis-ci.org/mxcl/PromiseKit
[ci-master]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=master
[ci-legacy]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=legacy-1.x
[ci-swift2]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.x
[ci-23]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.3-minimal-changes
[ci-22]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.2-minimal-changes
[ci-20]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.0-minimal-changes
[news-2]: http://promisekit.org/news/2015/05/PromiseKit-2.0-Released/
[news-3]: https://github.com/mxcl/PromiseKit/blob/master/CHANGELOG.markdown#300-oct-1st-2015
[news-4]: http://promisekit.org/news/2016/09/PromiseKit-4.0-Released/
[swift-2.3-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.3-minimal-changes
[swift-2.2-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.2-minimal-changes
[swift-2.0-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.0-minimal-changes
[promisekit.org]: http://promisekit.org/docs/
[badge-pod]: https://img.shields.io/cocoapods/v/PromiseKit.svg?label=version
[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20watchOS%20%7C%20tvOS-lightgrey.svg
[badge-languages]: https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg
[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg
[badge-pms]: https://img.shields.io/badge/supports-CocoaPods%20%7C%20Carthage%20%7C%20SwiftPM-green.svg
[OMGHTTPURLRQ]: https://github.com/mxcl/OMGHTTPURLRQ
[Alamofire]: http://alamofire.org
[AFNetworking]: https://github.com/AFNetworking/AFNetworking
[csotiriou/AFNetworking]: https://github.com/csotiriou/AFNetworking-PromiseKit
[CocoaPods]: http://cocoapods.org
[Carthage]: 2016-09-05-PromiseKit-4.0-Released

View File

@ -1,236 +0,0 @@
![PromiseKit](http://promisekit.org/public/img/logo-tight.png)
![badge-pod] ![badge-languages] ![badge-pms] ![badge-platforms] ![badge-mit]
[English](README.markdown)
---
現今的程式開發大量使用非同步存取, 難道不正是時候該開始考慮使用合適的工具讓非同步程式更加的強大, 易用, 並且使用愉快?
```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 語言完整實作 Promise 概念的工具套件. 除了能夠完美的和現有的 Objective-C 程式進行整合之外, 也支援多個不同平台, 如, iOS, macOS, tvOs 以及 watchOS.
# 快速入門
我們推薦使用 [CocoaPods] 或 [Carthage] 等套件管理程式來進行安裝. 如不使用套件管理程式安裝, 也可以手動下載相關程式, 並把 `PromiseKit.xcodeproj` 拖曳加入您的專案中, 並將 `PromiseKit.framework` 加入.
## Xcode 8 / Swift 3
```ruby
# 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)
]
)
```
## Xcode 8 / Swift 2.3 or Xcode 7
```ruby
# CocoaPods
swift_version = "2.3"
pod "PromiseKit", "~> 3.5"
# Carthage
github "mxcl/PromiseKit" ~> 3.5
```
# 相關文件
您可以在 [promisekit.org] 查詢完整的相關文件.
## 總覽
使用 `then` 定義非同步的執行任務:
```swift
login().then { json in
//…
}
```
鏈結使用:
```swift
login().then { json -> Promise<UIImage> in
return fetchAvatar(json["username"])
}.then { avatarImage in
self.imageView.image = avatarImage
}
```
串連式的錯誤/例外處理:
```swift
login().then {
return fetchAvatar()
}.then { avatarImage in
//…
}.catch { error in
UIAlertView(/*…*/).show()
}
```
組合應用:
```swift
let username = login().then{ $0["username"] }
when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}.then { image in
//…
}
```
毫無難度的重構:
```swift
func avatar() -> Promise<UIImage> {
let username = login().then{ $0["username"] }
return when(username, CLLocationManager.promise()).then { user, location in
return fetchAvatar(user, location: location)
}
}
```
您可以輕易地建構一個非同步任務:
```swift
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 vs. Xcode
PromiseKit 使用 Swift 進行開發, 下表列出 Xcode 以及 Swifit 的相關對應版本:
| Swift | Xcode | PromiseKit | CI Status | Release Notes |
| ----- | ----- | ---------- | ------------ | ----------------- |
| 3 | 8 | 4 | ![ci-master] | [2016/09][news-4] |
| 2 | 7/8 | 3 | ![ci-swift2] | [2015/10][news-3] |
| 1 | 7 | 3 | | [2015/10][news-3] |
| *N/A* | * | 1† | ![ci-legacy] | |
† 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] | ![ci-23] |
| 7.3 | 2.2 | 2 | [swift-2.2-minimal-changes] | ![ci-22] |
| 7.2 | 2.2 | 2 | [swift-2.2-minimal-changes] | ![ci-22] |
| 7.1 | 2.1 | 2 | [swift-2.0-minimal-changes] | ![ci-20] |
| 7.0 | 2.0 | 2 | [swift-2.0-minimal-changes] | ![ci-20] |
我們通常**不會**再對上述的分支進行維護, 但如果有任何的 PR 我們也歡迎提交.
# 相關擴充
Promises 僅對執行非同步任務非常有用, 因此我們把 Apple 絕大部份的 API 轉換成 Promises. 透過 CocoaPod 導入套件時即預設帶入 UIKit 和 Foundation, 而其他框架需要在您的 `Podfile` 檔案中進行額外的設定, 例如:
```ruby
pod "PromiseKit/MapKit" # MKDirections().promise().then { /*…*/ }
pod "PromiseKit/CoreLocation" # CLLocationManager.promise().then { /*…*/ }
```
我們所有相關的擴充專案可以到 [PromiseKit org ](https://github.com/PromiseKit) 查詢.
使用 `Cartfile` 進行設定:
```ruby
github "PromiseKit/MapKit" ~> 1.0
```
## 選擇使用網路相關函式庫
`URLSession` 一般來說很難勝任複雜的網路存取相關任務; 建議使用 [Alamofire] 或者 [OMGHTTPURLRQ]:
```swift
// 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].
# 有轉換您現有的程式碼到 Promises 的需求嗎?
[與我聯繫](mailto:mxcl@me.com), 我在 iOS 上使用 Promises 進行開發已經有多年的經驗, 同時也有 10 年以上開發行動裝置 App 的經驗.
# 支援
可以在 [Gitter chat channel](https://gitter.im/mxcl/PromiseKit) 詢問相關問題, 或者直接追蹤我們的 [bug tracker](https://github.com/mxcl/PromiseKit/issues/new)
[travis]: https://travis-ci.org/mxcl/PromiseKit
[ci-master]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=master
[ci-legacy]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=legacy-1.x
[ci-swift2]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.x
[ci-23]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.3-minimal-changes
[ci-22]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.2-minimal-changes
[ci-20]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=swift-2.0-minimal-changes
[news-2]: http://promisekit.org/news/2015/05/PromiseKit-2.0-Released/
[news-3]: https://github.com/mxcl/PromiseKit/blob/master/CHANGELOG.markdown#300-oct-1st-2015
[news-4]: http://promisekit.org/news/2016/09/PromiseKit-4.0-Released/
[swift-2.3-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.3-minimal-changes
[swift-2.2-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.2-minimal-changes
[swift-2.0-minimal-changes]: https://github.com/mxcl/PromiseKit/tree/swift-2.0-minimal-changes
[promisekit.org]: http://promisekit.org/docs/
[badge-pod]: https://img.shields.io/cocoapods/v/PromiseKit.svg?label=version
[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20watchOS%20%7C%20tvOS-lightgrey.svg
[badge-languages]: https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg
[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg
[badge-pms]: https://img.shields.io/badge/supports-CocoaPods%20%7C%20Carthage%20%7C%20SwiftPM-green.svg
[OMGHTTPURLRQ]: https://github.com/mxcl/OMGHTTPURLRQ
[Alamofire]: http://alamofire.org
[AFNetworking]: https://github.com/AFNetworking/AFNetworking
[csotiriou/AFNetworking]: https://github.com/csotiriou/AFNetworking-PromiseKit
[CocoaPods]: http://cocoapods.org
[Carthage]: 2016-09-05-PromiseKit-4.0-Released

View File

@ -61,36 +61,43 @@ import Foundation
}
/// - See: `Promise.then()`
@discardableResult
public func then<T>(on q: DispatchQueue = .default, execute body: @escaping (Any?) throws -> T) -> Promise<T> {
return asPromise().then(on: q, execute: body)
}
/// - See: `Promise.then()`
@discardableResult
public func then(on q: DispatchQueue = .default, execute body: @escaping (Any?) throws -> AnyPromise) -> Promise<Any?> {
return asPromise().then(on: q, execute: body)
}
/// - See: `Promise.then()`
@discardableResult
public func then<T>(on q: DispatchQueue = .default, execute body: @escaping (Any?) throws -> Promise<T>) -> Promise<T> {
return asPromise().then(on: q, execute: body)
}
/// - See: `Promise.always()`
@discardableResult
public func always(on q: DispatchQueue = .default, execute body: @escaping () -> Void) -> Promise<Any?> {
return asPromise().always(execute: body)
}
/// - See: `Promise.tap()`
@discardableResult
public func tap(on q: DispatchQueue = .default, execute body: @escaping (Result<Any?>) -> Void) -> Promise<Any?> {
return asPromise().tap(execute: body)
}
/// - See: `Promise.recover()`
@discardableResult
public func recover(on q: DispatchQueue = .default, policy: CatchPolicy = .allErrorsExceptCancellation, execute body: @escaping (Error) throws -> Promise<Any?>) -> Promise<Any?> {
return asPromise().recover(on: q, policy: policy, execute: body)
}
/// - See: `Promise.recover()`
@discardableResult
public func recover(on q: DispatchQueue = .default, policy: CatchPolicy = .allErrorsExceptCancellation, execute body: @escaping (Error) throws -> Any?) -> Promise<Any?> {
return asPromise().recover(on: q, policy: policy, execute: body)
}

View File

@ -27,6 +27,21 @@ public enum PMKError: Error {
case castError(Any.Type)
}
extension PMKError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidCallingConvention:
return "A closure was called with an invalid calling convention, probably (nil, nil)"
case .returnedSelf:
return "A promise handler returned itself"
case .whenConcurrentlyZero, .join:
return "Bad input was provided to a PromiseKit function"
case .castError(let type):
return "Promise chain sequence failed to cast an object to \(type)."
}
}
}
public enum PMKURLError: Error {
/**
The URLRequest succeeded but a valid UIImage could not be decoded from
@ -55,15 +70,15 @@ public enum PMKURLError: Error {
case .invalidImageData:
return nil
case .badResponse(_, _, let rsp):
return rsp as! Foundation.HTTPURLResponse
return rsp as? Foundation.HTTPURLResponse
case .stringEncoding(_, _, let rsp):
return rsp as! Foundation.HTTPURLResponse
return rsp as? Foundation.HTTPURLResponse
}
}
}
extension PMKURLError: CustomStringConvertible {
public var description: String {
extension PMKURLError: LocalizedError {
public var errorDescription: String? {
switch self {
case let .badResponse(rq, data, rsp):
if let data = data, let str = String(data: data, encoding: .utf8), let rsp = rsp {

View File

@ -15,6 +15,7 @@ extension Promise {
//
}
*/
@discardableResult
public func then(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> AnyPromise) -> Promise<Any?> {
return Promise<Any?>(sealant: { resolve in
state.then(on: q, else: resolve) { value in

View File

@ -146,6 +146,7 @@ open class Promise<T> {
//
}
*/
@discardableResult
public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> U) -> Promise<U> {
return Promise<U> { resolve in
state.then(on: q, else: resolve) { value in
@ -169,6 +170,7 @@ open class Promise<T> {
//
}
*/
@discardableResult
public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> Promise<U>) -> Promise<U> {
var resolve: ((Resolution<U>) -> Void)!
let rv = Promise<U>{ resolve = $0 }
@ -199,26 +201,31 @@ open class Promise<T> {
//
}
*/
@discardableResult
public func then<U, V>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> (Promise<U>, Promise<V>)) -> Promise<(U, V)> {
return then(on: q, execute: body) { when(fulfilled: $0.0, $0.1) }
}
/// This variant of `then` allows returning a tuple of promises within provided closure.
@discardableResult
public func then<U, V, X>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> (Promise<U>, Promise<V>, Promise<X>)) -> Promise<(U, V, X)> {
return then(on: q, execute: body) { when(fulfilled: $0.0, $0.1, $0.2) }
}
/// This variant of `then` allows returning a tuple of promises within provided closure.
@discardableResult
public func then<U, V, X, Y>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> (Promise<U>, Promise<V>, Promise<X>, Promise<Y>)) -> Promise<(U, V, X, Y)> {
return then(on: q, execute: body) { when(fulfilled: $0.0, $0.1, $0.2, $0.3) }
}
/// This variant of `then` allows returning a tuple of promises within provided closure.
@discardableResult
public func then<U, V, X, Y, Z>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> (Promise<U>, Promise<V>, Promise<X>, Promise<Y>, Promise<Z>)) -> Promise<(U, V, X, Y, Z)> {
return then(on: q, execute: body) { when(fulfilled: $0.0, $0.1, $0.2, $0.3, $0.4) }
}
/// utility function to serve `then` implementations with `body` returning tuple of promises
@discardableResult
private func then<U, V>(on q: DispatchQueue, execute body: @escaping (T) throws -> V, when: @escaping (V) -> Promise<U>) -> Promise<U> {
return Promise<U> { resolve in
state.then(on: q, else: resolve) { value in
@ -266,6 +273,7 @@ open class Promise<T> {
- Parameter execute: The handler to execute if this promise is rejected.
- SeeAlso: [Cancellation](http://promisekit.org/docs/)
*/
@discardableResult
public func recover(on q: DispatchQueue = .default, policy: CatchPolicy = .allErrorsExceptCancellation, execute body: @escaping (Error) throws -> Promise) -> Promise {
var resolve: ((Resolution<T>) -> Void)!
let rv = Promise{ resolve = $0 }
@ -292,6 +300,7 @@ open class Promise<T> {
- Parameter execute: The handler to execute if this promise is rejected.
- SeeAlso: [Cancellation](http://promisekit.org/docs/)
*/
@discardableResult
public func recover(on q: DispatchQueue = .default, policy: CatchPolicy = .allErrorsExceptCancellation, execute body: @escaping (Error) throws -> T) -> Promise {
return Promise { resolve in
state.catch(on: q, policy: policy, else: resolve) { error in

View File

@ -208,7 +208,7 @@ extension UnsealedState: CustomStringConvertible {
rv = "\(resolution)"
}
}
return "UnsealedState: \(rv)"
return "UnsealedState: \(rv!)"
}
}

View File

@ -177,7 +177,11 @@ public func when<T, PromiseIterator: IteratorProtocol>(fulfilled promiseIterator
func testDone() {
barrier.sync {
if pendingPromises == 0 {
#if !swift(>=3.3) || (swift(>=4) && !swift(>=4.1))
root.fulfill(promises.flatMap{ $0.value })
#else
root.fulfill(promises.compactMap{ $0.value })
#endif
}
}
}