Compare commits
1 Commits
master
...
charlesmch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b7d2c33e2 |
@ -18,8 +18,7 @@ script:
|
||||
Mac)
|
||||
xcodebuild -scheme PromiseKit -enableCodeCoverage YES test | xcpretty;;
|
||||
iOS|tvOS)
|
||||
xcrun instruments -w "$UUID" || true;
|
||||
sleep 15;
|
||||
open -a "simulator" --args -CurrentDeviceUDID "$UUID"
|
||||
xcodebuild -scheme PromiseKit -destination "id=$UUID" -enableCodeCoverage YES test | xcpretty;;
|
||||
watchOS)
|
||||
xcodebuild -scheme PromiseKit -destination "name=Apple Watch - 38mm" | xcpretty;;
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
# [3.0.0](https://github.com/mxcl/PromiseKit/releases/tag/3.0.0) Oct 1st, 2015
|
||||
|
||||
In Swift 2.0 `catch` and `defer` became reserved keywords mandating we rename our functions with these names. This forced a major semantic version change on PromiseKit and thus we took the opportunity to make other minor (source compatability breaking) improvements.
|
||||
In Swift 2.0 `catch` and `defer` became reserved keywords mandating we rename our functions with these names. This forced a major semantic version change on PromiseKit and thus we took the opportunity to make other minor (source compatibility breaking) improvements.
|
||||
|
||||
Thus if you cannot afford to adapt to PromiseKit 3 but still want to use Xcode-7.0/Swift-2.0 we provide a [minimal changes branch] where `catch` and `defer` are renamed `catch_` and `defer_` and all other changes are the bare minimum to make PromiseKit 2 compile against Swift 2.
|
||||
|
||||
|
||||
16
Checkouts/PromiseKit/Extensions/CloudKit/Package.swift
Normal file
16
Checkouts/PromiseKit/Extensions/CloudKit/Package.swift
Normal file
@ -0,0 +1,16 @@
|
||||
import PackageDescription
|
||||
|
||||
let pkg = Package(name: "PMKCloudKit")
|
||||
|
||||
pkg.dependencies = [
|
||||
.Package(url: "https://github.com/mxcl/PromiseKit.git", majorVersion: 4)
|
||||
]
|
||||
|
||||
pkg.exclude = [
|
||||
"Sources/CKContainer+AnyPromise.h",
|
||||
"Sources/CKDatabase+AnyPromise.h",
|
||||
"Sources/PMKCloudKit.h",
|
||||
"Sources/CKContainer+AnyPromise.m",
|
||||
"Sources/CKDatabase+AnyPromise.m",
|
||||
"Tests"
|
||||
]
|
||||
@ -2,14 +2,29 @@ language: objective-c
|
||||
osx_image: xcode8
|
||||
|
||||
env:
|
||||
- ACTION=test PLATFORM=Mac DESTINATION='platform=OS X'
|
||||
- ACTION=test PLATFORM=iOS DESTINATION='platform=iOS Simulator,name=iPhone 6S' UUID='7FC06F6D-AF72-4B38-9A96-1F934EA2E27F'
|
||||
- ACTION=test PLATFORM=tvOS DESTINATION='platform=tvOS Simulator,name=Apple TV 1080p' UUID='0DF1B136-A3A7-4C51-AE6E-CFEFDF52DA24'
|
||||
- ACTION=build PLATFORM=watchOS DESTINATION='platform=watchOS Simulator,name=Apple Watch - 38mm'
|
||||
- PLATFORM=Mac
|
||||
- PLATFORM=iOS NAME='iPhone SE'
|
||||
- PLATFORM=tvOS NAME='Apple TV 1080p'
|
||||
- PLATFORM=watchOS
|
||||
|
||||
install:
|
||||
before_install:
|
||||
- carthage bootstrap --platform $PLATFORM
|
||||
- if [ -n "$NAME" ]; then
|
||||
export UUID=$(instruments -s | ruby -e "ARGF.each_line{ |ln| ln =~ /$NAME .* \[(.*)\]/; if \$1; puts(\$1); exit; end }");
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ -n "$UUID" ]; then xcrun instruments -w "$UUID" || true; sleep 15; fi
|
||||
- set -o pipefail && xcodebuild -scheme PMKFoundation -destination "$DESTINATION" $ACTION | xcpretty
|
||||
- set -o pipefail;
|
||||
case $PLATFORM in
|
||||
Mac)
|
||||
xcodebuild -scheme PMKFoundation -enableCodeCoverage YES test | xcpretty;;
|
||||
iOS|tvOS)
|
||||
xcrun instruments -w "$UUID" || true;
|
||||
sleep 15;
|
||||
xcodebuild -scheme PMKFoundation -destination "id=$UUID" -enableCodeCoverage YES test | xcpretty;;
|
||||
watchOS)
|
||||
xcodebuild -scheme PMKFoundation -destination "name=Apple Watch - 38mm" | xcpretty;;
|
||||
esac
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
@ -315,7 +315,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 1.0.4;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@ -344,8 +344,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
};
|
||||
name = Debug;
|
||||
@ -374,7 +372,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 1.0.4;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@ -396,8 +394,6 @@
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@ -10,5 +10,6 @@ let package = Package(
|
||||
"Sources/NSTask+AnyPromise.m",
|
||||
"Sources/NSURLSession+AnyPromise.m",
|
||||
"Sources/PMKFoundation.h",
|
||||
"Tests" // currently SwiftPM is not savvy to having a single test…
|
||||
]
|
||||
)
|
||||
|
||||
@ -20,10 +20,10 @@ import PromiseKit
|
||||
*/
|
||||
extension NotificationCenter {
|
||||
/// Observe the named notification once
|
||||
public func observe(once name: String) -> NotificationPromise {
|
||||
public func observe(once name: Notification.Name, object: Any? = nil) -> NotificationPromise {
|
||||
let (promise, fulfill) = NotificationPromise.go()
|
||||
let id = addObserver(forName: NSNotification.Name(rawValue: name), object: nil, queue: nil, using: fulfill)
|
||||
_ = promise.then(on: zalgo) { _ in self.removeObserver(id) }
|
||||
let id = addObserver(forName: name, object: object, queue: nil, using: fulfill)
|
||||
_ = promise.always { self.removeObserver(id) }
|
||||
return promise
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import Foundation
|
||||
#if !COCOAPODS
|
||||
import PromiseKit
|
||||
#endif
|
||||
|
||||
public enum Encoding {
|
||||
/// Decode as JSON
|
||||
|
||||
@ -14,10 +14,10 @@ class NSNotificationCenterTests: XCTestCase {
|
||||
ex.fulfill()
|
||||
}
|
||||
|
||||
NotificationCenter.default.post(name: Notification.Name(rawValue: PMKTestNotification), object: nil, userInfo: userInfo)
|
||||
NotificationCenter.default.post(name: PMKTestNotification, object: nil, userInfo: userInfo)
|
||||
|
||||
waitForExpectations(timeout: 1, handler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private let PMKTestNotification = "PMKTestNotification"
|
||||
private let PMKTestNotification = Notification.Name("PMKTestNotification")
|
||||
|
||||
@ -508,7 +508,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 1.0.3;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@ -537,8 +537,6 @@
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
};
|
||||
name = Debug;
|
||||
@ -567,7 +565,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 1.0.3;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@ -589,8 +587,6 @@
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3,4";
|
||||
TVOS_DEPLOYMENT_TARGET = 9.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
@return A promise that fulfills with a boolean NSNumber indicating
|
||||
whether or not the animations actually finished.
|
||||
*/
|
||||
+ (AnyPromise *)promiseWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
|
||||
+ (AnyPromise *)promiseWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Animate changes to one or more views using the specified duration, delay,
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
49A5583D1DC33BD000E4D01B /* 03_JointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A5583B1DC33BC800E4D01B /* 03_JointTests.swift */; };
|
||||
49A5584D1DC5185900E4D01B /* 03_WrapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A5584B1DC5172F00E4D01B /* 03_WrapTests.swift */; };
|
||||
6314112B1D5978D700E24B9E /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
|
||||
631411311D5978EB00E24B9E /* PMKDefaultDispatchQueueTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D641B1D59635300BC0AF5 /* PMKDefaultDispatchQueueTest.swift */; };
|
||||
631411381D59795700E24B9E /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
|
||||
@ -104,6 +106,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
49A5583B1DC33BC800E4D01B /* 03_JointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = 03_JointTests.swift; path = Tests/CorePromise/03_JointTests.swift; sourceTree = "<group>"; };
|
||||
49A5584B1DC5172F00E4D01B /* 03_WrapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = 03_WrapTests.swift; path = Tests/CorePromise/03_WrapTests.swift; sourceTree = "<group>"; };
|
||||
630019221D596292003B4E30 /* PMKCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6314112F1D5978D700E24B9E /* PMKDispatchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKDispatchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6314113C1D59795700E24B9E /* PMKBridgeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKBridgeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -253,10 +257,12 @@
|
||||
635D640F1D59635300BC0AF5 /* 03_HangTests.m */,
|
||||
635D64101D59635300BC0AF5 /* 03_JoinTests.m */,
|
||||
635D64111D59635300BC0AF5 /* 03_JoinTests.swift */,
|
||||
49A5583B1DC33BC800E4D01B /* 03_JointTests.swift */,
|
||||
635D64121D59635300BC0AF5 /* 03_RaceTests.swift */,
|
||||
635D64131D59635300BC0AF5 /* 03_WhenConcurrentTests.swift */,
|
||||
635D64141D59635300BC0AF5 /* 03_WhenTests.m */,
|
||||
635D64151D59635300BC0AF5 /* 03_WhenTests.swift */,
|
||||
49A5584B1DC5172F00E4D01B /* 03_WrapTests.swift */,
|
||||
6352FDE41D69415D00680F48 /* 04_VerifySubclassing.swift */,
|
||||
635D64161D59635300BC0AF5 /* 98_StressTests.swift */,
|
||||
635D64171D59635300BC0AF5 /* 99_RegressionTests.swift */,
|
||||
@ -538,6 +544,7 @@
|
||||
files = (
|
||||
635D641E1D59635300BC0AF5 /* 02_CancellationTests.swift in Sources */,
|
||||
635D64201D59635300BC0AF5 /* 02_ErrorUnhandlerTests.swift in Sources */,
|
||||
49A5583D1DC33BD000E4D01B /* 03_JointTests.swift in Sources */,
|
||||
635D64221D59635300BC0AF5 /* 02_ZalgoTests.swift in Sources */,
|
||||
635D64211D59635300BC0AF5 /* 02_PMKManifoldTests.m in Sources */,
|
||||
635D64251D59635300BC0AF5 /* 03_JoinTests.m in Sources */,
|
||||
@ -547,6 +554,7 @@
|
||||
635D641D1D59635300BC0AF5 /* 01_PromiseTests.swift in Sources */,
|
||||
635D64261D59635300BC0AF5 /* 03_JoinTests.swift in Sources */,
|
||||
635D64231D59635300BC0AF5 /* 03_AfterTests.swift in Sources */,
|
||||
49A5584D1DC5185900E4D01B /* 03_WrapTests.swift in Sources */,
|
||||
6352FDE51D69415D00680F48 /* 04_VerifySubclassing.swift in Sources */,
|
||||
635D642A1D59635300BC0AF5 /* 03_WhenTests.swift in Sources */,
|
||||
635D64281D59635300BC0AF5 /* 03_WhenConcurrentTests.swift in Sources */,
|
||||
@ -758,7 +766,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 4.0.4;
|
||||
CURRENT_PROJECT_VERSION = 4.0.5;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@ -808,7 +816,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 4.0.4;
|
||||
CURRENT_PROJECT_VERSION = 4.0.5;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
|
||||
@ -6,7 +6,7 @@ Modern development is highly asynchronous: isn’t it about time we had tools th
|
||||
made programming asynchronously powerful, easy and delightful?
|
||||
|
||||
```swift
|
||||
UIApplication.shared.networkActivityIndicatorVisible = true
|
||||
UIApplication.shared.isNetworkActivityIndicatorVisible = true
|
||||
|
||||
firstly {
|
||||
when(URLSession.dataTask(with: url).asImage(), CLLocationManager.promise())
|
||||
@ -14,7 +14,7 @@ firstly {
|
||||
self.imageView.image = image;
|
||||
self.label.text = "\(location)"
|
||||
}.always {
|
||||
UIApplication.shared.networkActivityIndicatorVisible = false
|
||||
UIApplication.shared.isNetworkActivityIndicatorVisible = false
|
||||
}.catch { error in
|
||||
UIAlertView(/*…*/).show()
|
||||
}
|
||||
|
||||
@ -41,7 +41,8 @@ import Foundation
|
||||
}
|
||||
|
||||
/**
|
||||
Bridge an AnyPromise to a Promise<Any>
|
||||
Bridges an `AnyPromise` to a `Promise<Any?>`.
|
||||
|
||||
- Note: AnyPromises fulfilled with `PMKManifold` lose all but the first fulfillment object.
|
||||
- Remark: Could not make this an initializer of `Promise` due to generics issues.
|
||||
*/
|
||||
@ -126,7 +127,7 @@ import Foundation
|
||||
|
||||
- Note: If the AnyPromise was fulfilled with a `PMKManifold`, returns only the first fulfillment object.
|
||||
|
||||
- Returns If `resolved`, the object that was used to resolve this promise; if `pending`, nil.
|
||||
- Returns: The value with which this promise was resolved or `nil` if this promise is pending.
|
||||
*/
|
||||
@objc private var __value: Any? {
|
||||
switch state.get() {
|
||||
@ -142,7 +143,7 @@ import Foundation
|
||||
/**
|
||||
Creates a resolved promise.
|
||||
|
||||
When developing your own promise systems, it is ocassionally useful to be able to return an already resolved promise.
|
||||
When developing your own promise systems, it is occasionally useful to be able to return an already resolved promise.
|
||||
|
||||
- Parameter value: The value with which to resolve this promise. Passing an `NSError` will cause the promise to be rejected, passing an AnyPromise will return a new AnyPromise bound to that promise, otherwise the promise will be fulfilled with the value passed.
|
||||
|
||||
@ -255,6 +256,9 @@ import Foundation
|
||||
|
||||
|
||||
extension AnyPromise {
|
||||
/**
|
||||
- Returns: A description of the state of this promise.
|
||||
*/
|
||||
override public var description: String {
|
||||
return "AnyPromise: \(state)"
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import Dispatch
|
||||
|
||||
/**
|
||||
```
|
||||
DispatchQueue.global().promise {
|
||||
try md5(input)
|
||||
}.then { md5 in
|
||||
//…
|
||||
}
|
||||
```
|
||||
|
||||
- Parameter body: The closure that resolves this promise.
|
||||
- Returns: A new promise resolved by the result of the provided closure.
|
||||
*/
|
||||
extension DispatchQueue {
|
||||
/**
|
||||
Submits a block for asynchronous execution on a dispatch queue.
|
||||
|
||||
DispatchQueue.global().promise {
|
||||
try md5(input)
|
||||
}.then { md5 in
|
||||
//…
|
||||
}
|
||||
|
||||
- Parameter body: The closure that resolves this promise.
|
||||
- Returns: A new promise resolved by the result of the provided closure.
|
||||
|
||||
- SeeAlso: `DispatchQueue.async(group:qos:flags:execute:)`
|
||||
- SeeAlso: `dispatch_promise()`
|
||||
- SeeAlso: `dispatch_promise_on()`
|
||||
*/
|
||||
@ -35,6 +35,10 @@ extension DispatchQueue {
|
||||
public final func promise<T>(group: DispatchGroup? = nil, qos: DispatchQoS = .default, flags: DispatchWorkItemFlags = [], execute body: () throws -> Promise<T>) -> Promise<T> { fatalError() }
|
||||
|
||||
/**
|
||||
The default queue for all handlers.
|
||||
|
||||
Defaults to `DispatchQueue.main`.
|
||||
|
||||
- SeeAlso: `PMKDefaultDispatchQueue()`
|
||||
- SeeAlso: `PMKSetDefaultDispatchQueue()`
|
||||
*/
|
||||
|
||||
@ -5,19 +5,19 @@ public enum PMKError: Error {
|
||||
The ErrorType for a rejected `join`.
|
||||
- Parameter 0: The promises passed to this `join` that did not *all* fulfill.
|
||||
- Note: The array is untyped because Swift generics are fussy with enums.
|
||||
*/
|
||||
*/
|
||||
case join([AnyObject])
|
||||
|
||||
/**
|
||||
The completionHandler with form (T?, ErrorType?) was called with (nil, nil)
|
||||
This is invalid as per Cocoa/Apple calling conventions.
|
||||
*/
|
||||
*/
|
||||
case invalidCallingConvention
|
||||
|
||||
/**
|
||||
A handler returned its own promise. 99% of the time, this is likely a
|
||||
programming error. It is also invalid per Promises/A+.
|
||||
*/
|
||||
*/
|
||||
case returnedSelf
|
||||
|
||||
/** `when()` was called with a concurrency of <= 0 */
|
||||
@ -31,25 +31,25 @@ public enum PMKURLError: Error {
|
||||
/**
|
||||
The URLRequest succeeded but a valid UIImage could not be decoded from
|
||||
the data that was received.
|
||||
*/
|
||||
*/
|
||||
case invalidImageData(URLRequest, Data)
|
||||
|
||||
/**
|
||||
The HTTP request returned a non-200 status code.
|
||||
*/
|
||||
*/
|
||||
case badResponse(URLRequest, Data?, URLResponse?)
|
||||
|
||||
/**
|
||||
The data could not be decoded using the encoding specified by the HTTP
|
||||
response headers.
|
||||
*/
|
||||
*/
|
||||
case stringEncoding(URLRequest, Data, URLResponse)
|
||||
|
||||
/**
|
||||
Usually the `NSURLResponse` is actually an `NSHTTPURLResponse`, if so you
|
||||
can access it using this property. Since it is returned as an unwrapped
|
||||
optional: be sure.
|
||||
*/
|
||||
*/
|
||||
public var NSHTTPURLResponse: Foundation.HTTPURLResponse! {
|
||||
switch self {
|
||||
case .invalidImageData:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
extension Promise {
|
||||
/**
|
||||
- Returns: The error with which this promise was rejected; `nil` if this promise is not rejected.
|
||||
*/
|
||||
*/
|
||||
public var error: Error? {
|
||||
switch state.get() {
|
||||
case .none:
|
||||
@ -15,35 +15,35 @@ extension Promise {
|
||||
|
||||
/**
|
||||
- Returns: `true` if the promise has not yet resolved.
|
||||
*/
|
||||
*/
|
||||
public var isPending: Bool {
|
||||
return state.get() == nil
|
||||
}
|
||||
|
||||
/**
|
||||
- Returns: `true` if the promise has resolved.
|
||||
*/
|
||||
*/
|
||||
public var isResolved: Bool {
|
||||
return !isPending
|
||||
}
|
||||
|
||||
/**
|
||||
- Returns: `true` if the promise was fulfilled.
|
||||
*/
|
||||
*/
|
||||
public var isFulfilled: Bool {
|
||||
return value != nil
|
||||
}
|
||||
|
||||
/**
|
||||
- Returns: `true` if the promise was rejected.
|
||||
*/
|
||||
*/
|
||||
public var isRejected: Bool {
|
||||
return error != nil
|
||||
}
|
||||
|
||||
/**
|
||||
- Returns: The value with which this promise was fulfilled or `nil` if this promise is pending or rejected.
|
||||
*/
|
||||
*/
|
||||
public var value: T? {
|
||||
switch state.get() {
|
||||
case .none:
|
||||
|
||||
@ -35,8 +35,8 @@ open class Promise<T> {
|
||||
}
|
||||
|
||||
- Parameter resolvers: The provided closure is called immediately on the active thread; commence your asynchronous task, calling either fulfill or reject when it completes.
|
||||
- Parameter fulfill: Fulfills this promise with the provided value.
|
||||
- Parameter reject: Rejects this promise with the provided error.
|
||||
- Parameter fulfill: Fulfills this promise with the provided value.
|
||||
- Parameter reject: Rejects this promise with the provided error.
|
||||
|
||||
- Returns: A new promise.
|
||||
|
||||
@ -275,7 +275,7 @@ open class Promise<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
`tap` allows you to “tap” into a promise chain and inspect its result.
|
||||
Allows you to “tap” into a promise chain and inspect its result.
|
||||
|
||||
The function you provide cannot mutate the chain.
|
||||
|
||||
@ -401,6 +401,9 @@ public func firstly<T: Error>(execute body: () throws -> T) -> Promise<T> { fata
|
||||
@available(*, unavailable, message: "use DispatchQueue.promise")
|
||||
public func firstly<T>(on: DispatchQueue, execute body: () throws -> Promise<T>) -> Promise<T> { fatalError() }
|
||||
|
||||
/**
|
||||
- SeeAlso: `DispatchQueue.promise(group:qos:flags:execute:)`
|
||||
*/
|
||||
@available(*, deprecated: 4.0, renamed: "DispatchQueue.promise")
|
||||
public func dispatch_promise<T>(_ on: DispatchQueue, _ body: @escaping () throws -> T) -> Promise<T> {
|
||||
return Promise(value: ()).then(on: on, execute: body)
|
||||
@ -409,7 +412,7 @@ public func dispatch_promise<T>(_ on: DispatchQueue, _ body: @escaping () throws
|
||||
|
||||
/**
|
||||
The underlying resolved state of a promise.
|
||||
- remark: Same as `Resolution<T>` but without the associated `ErrorConsumptionToken`.
|
||||
- Remark: Same as `Resolution<T>` but without the associated `ErrorConsumptionToken`.
|
||||
*/
|
||||
public enum Result<T> {
|
||||
/// Fulfillment
|
||||
@ -426,6 +429,9 @@ public enum Result<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
- Returns: `true` if the result is `fulfilled` or `false` if it is `rejected`.
|
||||
*/
|
||||
public var boolValue: Bool {
|
||||
switch self {
|
||||
case .fulfilled:
|
||||
@ -436,18 +442,62 @@ public enum Result<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
An object produced by `Promise.joint()`, along with a promise to which it is bound.
|
||||
|
||||
Joining with a promise via `Promise.join(_:)` will pipe the resolution of that promise to
|
||||
the joint's bound promise.
|
||||
|
||||
- SeeAlso: `Promise.joint()`
|
||||
- SeeAlso: `Promise.join(_:)`
|
||||
*/
|
||||
public class PMKJoint<T> {
|
||||
fileprivate var resolve: ((Resolution<T>) -> Void)!
|
||||
}
|
||||
|
||||
extension Promise {
|
||||
public final class func joint() -> (Promise<T>, (PMKJoint<T>)) {
|
||||
/**
|
||||
Provides a safe way to instantiate a `Promise` and resolve it later via its joint and another
|
||||
promise.
|
||||
|
||||
class Engine {
|
||||
static func make() -> Promise<Engine> {
|
||||
let (enginePromise, joint) = Promise<Engine>.joint()
|
||||
let cylinder: Cylinder = Cylinder(explodeAction: {
|
||||
|
||||
// We *could* use an IUO, but there are no guarantees about when
|
||||
// this callback will be called. Having an actual promise is safe.
|
||||
|
||||
enginePromise.then { engine in
|
||||
engine.checkOilPressure()
|
||||
}
|
||||
})
|
||||
|
||||
firstly {
|
||||
Ignition.default.start()
|
||||
}.then { plugs in
|
||||
Engine(cylinders: [cylinder], sparkPlugs: plugs)
|
||||
}.join(joint)
|
||||
|
||||
return enginePromise
|
||||
}
|
||||
}
|
||||
|
||||
- Returns: A new promise and its joint.
|
||||
- SeeAlso: `Promise.join(_:)`
|
||||
*/
|
||||
public final class func joint() -> (Promise<T>, PMKJoint<T>) {
|
||||
let pipe = PMKJoint<T>()
|
||||
let promise = Promise(sealant: { pipe.resolve = $0 })
|
||||
return (promise, pipe)
|
||||
}
|
||||
|
||||
/**
|
||||
Pipes the value of this promise to the promise created with the joint.
|
||||
|
||||
- Parameter joint: The joint on which to join.
|
||||
- SeeAlso: `Promise.joint()`
|
||||
*/
|
||||
public func join(_ joint: PMKJoint<T>) {
|
||||
state.pipe(joint.resolve)
|
||||
}
|
||||
@ -456,7 +506,7 @@ extension Promise {
|
||||
|
||||
extension Promise where T: Collection {
|
||||
/**
|
||||
`map` transforms a `Promise` where `T` is a `Collection`, eg. an `Array` returning a `Promise<[U]>`
|
||||
Transforms a `Promise` where `T` is a `Collection` into a `Promise<[U]>`
|
||||
|
||||
URLSession.shared.dataTask(url: /*…*/).asArray().map { result in
|
||||
return download(result)
|
||||
|
||||
@ -54,7 +54,7 @@ extern AnyPromise * __nonnull PMKAfter(NSTimeInterval duration) NS_REFINED_FOR_S
|
||||
//…
|
||||
});
|
||||
|
||||
@warning *Important* In the event of rejection the other promises will continue to resolve and as per any other promise will eithe fulfill or reject. This is the right pattern for `getter` style asynchronous tasks, but often for `setter` tasks (eg. storing data on a server), you most likely will need to wait on all tasks and then act based on which have succeeded and which have failed. In such situations use `PMKJoin`.
|
||||
@warning *Important* In the event of rejection the other promises will continue to resolve and as per any other promise will either fulfill or reject. This is the right pattern for `getter` style asynchronous tasks, but often for `setter` tasks (eg. storing data on a server), you most likely will need to wait on all tasks and then act based on which have succeeded and which have failed. In such situations use `PMKJoin`.
|
||||
|
||||
@param input The input upon which to wait before resolving this promise.
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import class Dispatch.DispatchQueue
|
||||
import func Dispatch.__dispatch_barrier_sync
|
||||
import func Foundation.NSLog
|
||||
|
||||
enum Seal<T> {
|
||||
@ -82,7 +81,7 @@ class UnsealedState<T>: State<T> {
|
||||
Quick return, but will not provide the handlers array because
|
||||
it could be modified while you are using it by another thread.
|
||||
If you need the handlers, use the second `get` variant.
|
||||
*/
|
||||
*/
|
||||
override func get() -> Resolution<T>? {
|
||||
var result: Resolution<T>?
|
||||
barrier.sync {
|
||||
@ -104,7 +103,7 @@ class UnsealedState<T>: State<T> {
|
||||
}
|
||||
}
|
||||
if !sealed {
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
switch (self.seal) {
|
||||
case .pending:
|
||||
body(self.seal)
|
||||
@ -123,7 +122,7 @@ class UnsealedState<T>: State<T> {
|
||||
super.init()
|
||||
resolver = { resolution in
|
||||
var handlers: Handlers<T>?
|
||||
__dispatch_barrier_sync(self.barrier) {
|
||||
self.barrier.sync(flags: .barrier) {
|
||||
if case .pending(let hh) = self.seal {
|
||||
self.seal = .resolved(resolution)
|
||||
handlers = hh
|
||||
|
||||
@ -55,7 +55,7 @@ public let zalgo = DispatchQueue(label: "Zalgo")
|
||||
then is going to take some time and doesn’t interact with the UI.
|
||||
|
||||
Please note (again) that generally you should not use `zalgo` or `waldo`.
|
||||
The performance gains are neglible and we provide these functions only out
|
||||
The performance gains are negligible and we provide these functions only out
|
||||
of a misguided sense that library code should be as optimized as possible.
|
||||
If you use either without tests proving their correctness you may
|
||||
unwillingly introduce horrendous, near-impossible-to-trace bugs.
|
||||
|
||||
@ -40,7 +40,7 @@ public func join<T>(_ promises: [Promise<T>]) -> Promise<[T]> {
|
||||
return Promise { fulfill, reject in
|
||||
for promise in promises {
|
||||
promise.state.pipe { resolution in
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
if case .rejected(_, let token) = resolution {
|
||||
token.consumed = true // the parent Error.Join consumes all
|
||||
rejected = true
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
/**
|
||||
Resolves with the first resolving promise from a set of promises.
|
||||
|
||||
```
|
||||
race(promise1, promise2, promise3).then { winner in
|
||||
//…
|
||||
}
|
||||
```
|
||||
race(promise1, promise2, promise3).then { winner in
|
||||
//…
|
||||
}
|
||||
|
||||
- Returns: A new promise that resolves when the first promise in the provided promises resolves.
|
||||
- Warning: If any of the provided promises reject, the returned promise is rejected.
|
||||
@ -21,11 +19,9 @@ public func race<T>(promises: [Promise<T>]) -> Promise<T> {
|
||||
/**
|
||||
Resolves with the first resolving promise from a set of promises.
|
||||
|
||||
```
|
||||
race(promise1, promise2, promise3).then { winner in
|
||||
//…
|
||||
}
|
||||
```
|
||||
race(promise1, promise2, promise3).then { winner in
|
||||
//…
|
||||
}
|
||||
|
||||
- Returns: A new promise that resolves when the first promise in the provided promises resolves.
|
||||
- Warning: If any of the provided promises reject, the returned promise is rejected.
|
||||
|
||||
@ -20,7 +20,7 @@ private func _when<T>(_ promises: [Promise<T>]) -> Promise<Void> {
|
||||
|
||||
for promise in promises {
|
||||
promise.state.pipe { resolution in
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
switch resolution {
|
||||
case .rejected(let error, let token):
|
||||
token.consumed = true
|
||||
@ -145,7 +145,7 @@ public func when<T, PromiseIterator: IteratorProtocol>(fulfilled promiseIterator
|
||||
var index: Int!
|
||||
var promise: Promise<T>!
|
||||
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
guard let next = generator.next() else { return }
|
||||
|
||||
promise = next
|
||||
@ -168,7 +168,7 @@ public func when<T, PromiseIterator: IteratorProtocol>(fulfilled promiseIterator
|
||||
}
|
||||
|
||||
promise.state.pipe { resolution in
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
pendingPromises -= 1
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ public func when<T>(resolved promises: [Promise<T>]) -> Promise<[Result<T>]> {
|
||||
token.consumed = true // all errors are implicitly consumed
|
||||
}
|
||||
var done = false
|
||||
__dispatch_barrier_sync(barrier) {
|
||||
barrier.sync(flags: .barrier) {
|
||||
countdown -= 1
|
||||
done = countdown == 0
|
||||
}
|
||||
|
||||
@ -15,10 +15,10 @@
|
||||
public func wrap<T>(_ body: (@escaping (T?, Error?) -> Void) throws -> Void) -> Promise<T> {
|
||||
return Promise { fulfill, reject in
|
||||
try body { obj, err in
|
||||
if let obj = obj {
|
||||
fulfill(obj)
|
||||
} else if let err = err {
|
||||
if let err = err {
|
||||
reject(err)
|
||||
} else if let obj = obj {
|
||||
fulfill(obj)
|
||||
} else {
|
||||
reject(PMKError.invalidCallingConvention)
|
||||
}
|
||||
@ -39,14 +39,14 @@ public func wrap<T>(_ body: (@escaping (T, Error?) -> Void) throws -> Void) -> P
|
||||
}
|
||||
}
|
||||
|
||||
/// Some APIs unwiesly invert the Cocoa standard for completion-handlers.
|
||||
/// Some APIs unwisely invert the Cocoa standard for completion-handlers.
|
||||
public func wrap<T>(_ body: (@escaping (Error?, T?) -> Void) throws -> Void) -> Promise<T> {
|
||||
return Promise { fulfill, reject in
|
||||
try body { err, obj in
|
||||
if let obj = obj {
|
||||
fulfill(obj)
|
||||
} else if let err = err {
|
||||
if let err = err {
|
||||
reject(err)
|
||||
} else if let obj = obj {
|
||||
fulfill(obj)
|
||||
} else {
|
||||
reject(PMKError.invalidCallingConvention)
|
||||
}
|
||||
|
||||
@ -121,6 +121,26 @@ class BridgingTests: XCTestCase {
|
||||
XCTAssertEqual(PMKDummyAnyPromise_YES().asPromise().value as? NSNumber, NSNumber(value: true))
|
||||
}
|
||||
|
||||
func testFirstlyReturningAnyPromiseSuccess() {
|
||||
let ex = expectation(description: "")
|
||||
firstly {
|
||||
PMKDummyAnyPromise_Error()
|
||||
}.catch { error in
|
||||
ex.fulfill()
|
||||
}
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
|
||||
func testFirstlyReturningAnyPromiseError() {
|
||||
let ex = expectation(description: "")
|
||||
firstly {
|
||||
PMKDummyAnyPromise_YES()
|
||||
}.then { _ in
|
||||
ex.fulfill()
|
||||
}
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
|
||||
func test1() {
|
||||
let ex = expectation(description: "")
|
||||
|
||||
|
||||
53
Checkouts/PromiseKit/Tests/CorePromise/03_JointTests.swift
Normal file
53
Checkouts/PromiseKit/Tests/CorePromise/03_JointTests.swift
Normal file
@ -0,0 +1,53 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class JointTests: XCTestCase {
|
||||
func testPiping() {
|
||||
let (promise, joint) = Promise<Int>.joint()
|
||||
|
||||
XCTAssert(promise.isPending)
|
||||
|
||||
let foo = Promise(value: 3)
|
||||
foo.join(joint)
|
||||
|
||||
XCTAssertEqual(3, promise.value)
|
||||
}
|
||||
|
||||
func testPipingPending() {
|
||||
let (promise, joint) = Promise<Int>.joint()
|
||||
|
||||
XCTAssert(promise.isPending)
|
||||
|
||||
let (foo, fulfillFoo, _) = Promise<Int>.pending()
|
||||
foo.join(joint)
|
||||
|
||||
fulfillFoo(3)
|
||||
|
||||
XCTAssertEqual(3, promise.value)
|
||||
}
|
||||
|
||||
func testCallback() {
|
||||
let ex = expectation(description: "")
|
||||
|
||||
let (promise, joint) = Promise<Void>.joint()
|
||||
promise.then { ex.fulfill() }
|
||||
|
||||
Promise(value: ()).join(joint)
|
||||
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
|
||||
func testCallbackPending() {
|
||||
let ex = expectation(description: "")
|
||||
|
||||
let (promise, joint) = Promise<Void>.joint()
|
||||
promise.then { ex.fulfill() }
|
||||
|
||||
let (foo, fulfillFoo, _) = Promise<Void>.pending()
|
||||
foo.join(joint)
|
||||
|
||||
fulfillFoo()
|
||||
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
}
|
||||
70
Checkouts/PromiseKit/Tests/CorePromise/03_WrapTests.swift
Normal file
70
Checkouts/PromiseKit/Tests/CorePromise/03_WrapTests.swift
Normal file
@ -0,0 +1,70 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class WrapTests: XCTestCase {
|
||||
class KittenFetcher {
|
||||
let value: Int?
|
||||
let error: Error?
|
||||
|
||||
init(value: Int?, error: Error?) {
|
||||
self.value = value
|
||||
self.error = error
|
||||
}
|
||||
|
||||
func fetchWithCompletionBlock(block: (Int?, Error?) -> Void) {
|
||||
if value != nil {
|
||||
block(value, nil)
|
||||
} else {
|
||||
block(nil, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSuccess() {
|
||||
let kittenFetcher = KittenFetcher(value: 2, error: nil)
|
||||
let promise = PromiseKit.wrap { resolve in
|
||||
kittenFetcher.fetchWithCompletionBlock(block: resolve)
|
||||
}
|
||||
|
||||
XCTAssertTrue(promise.isFulfilled)
|
||||
XCTAssertEqual(2, promise.value)
|
||||
}
|
||||
|
||||
func testError() {
|
||||
enum Error: Swift.Error {
|
||||
case test
|
||||
}
|
||||
|
||||
let ex = expectation(description: "")
|
||||
|
||||
let kittenFetcher = KittenFetcher(value: nil, error: Error.test)
|
||||
let promise = PromiseKit.wrap { resolve in
|
||||
kittenFetcher.fetchWithCompletionBlock(block: resolve)
|
||||
}.catch { error in
|
||||
if case Error.test = error {
|
||||
ex.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
|
||||
func testInvalidCallingConvention() {
|
||||
enum Error: Swift.Error {
|
||||
case test
|
||||
}
|
||||
|
||||
let ex = expectation(description: "")
|
||||
|
||||
let kittenFetcher = KittenFetcher(value: nil, error: nil)
|
||||
let promise = PromiseKit.wrap { resolve in
|
||||
kittenFetcher.fetchWithCompletionBlock(block: resolve)
|
||||
}.catch { error in
|
||||
if case PMKError.invalidCallingConvention = error {
|
||||
ex.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user