-}
-
-@objc class Bar: NSObject { /*…*/ }
-```
-
-Ensure that your project is generating a `…-Swift.h` header so that Objective-C can see your Swift code.
-
-If you built this project and opened the `…-Swift.h` header, you would only see this:
-
-```objc
-@interface Foo
-@end
-
-@interface Bar
-@end
-```
-
-That's because Objective-C cannot import Swift objects that are generic. So we need to write some stubs:
-
-```swift
-@objc class Foo: NSObject {
- @objc func stringPromise() -> AnyPromise {
- return AnyPromise(stringPromise())
- }
- @objc func barPromise() -> AnyPromise {
- return AnyPromise(barPromise())
- }
-}
-```
-
-If we built this and opened our generated header, we would now see:
-
-```objc
-@interface Foo
-- (AnyPromise *)stringPromise;
-- (AnyPromise *)barPromise;
-@end
-
-@interface Bar
-@end
-```
-
-Perfect.
-
-Note that AnyPromise can only bridge objects that conform to `AnyObject` or derive from `NSObject`. This is a limitation of Objective-C.
-
-# Using ObjC AnyPromises from Swift
-
-Simply use them, the type of your handler parameter is `Any`:
-
-```objective-c
-- (AnyPromise *)fetchThings {
- return [AnyPromise promiseWithValue:@[@"a", @"b", @"c"]];
-}
-```
-
-Since ObjC is not type-safe and Swift is, you will (probably) need to cast the `Any` to whatever it is you actually are feeding:
-
-```swift
-Foo.fetchThings().done { any in
- let bar = any as! [String]
-}
-```
-
-## :warning: Caution:
-
-ARC in Objective-C, unlike in Objective-C++, is not exception-safe by default.
-So, throwing an error will result in keeping a strong reference to the closure
-that contains the throw statement.
-This pattern will consequently result in memory leaks if you're not careful.
-
-> *Note:* Only having a strong reference to the closure would result in memory leaks.
-> In our case, PromiseKit automatically keeps a strong reference to the closure until it's released.
-
-__Workarounds:__
-
-1. Return a Promise with value NSError\
-Instead of throwing a normal error, you can return a Promise with value NSError instead.
-
-```objc
-myPromise.then(^{
- return [AnyPromise promiseWithValue:[NSError myCustomError]];
-}).catch(^(NSError *error){
- if ([error isEqual:[NSError myCustomError]]) {
- // In case, same error as the one we thrown
- return;
- }
- //…
-});
-```
-2. Enable ARC for exceptions in Objective-C (not recommended)\
-You can add this ```-fobjc-arc-exceptions to your``` to your compiler flags to enable ARC for exceptions.
-This is not recommended unless you've read the Apple documentation and are comfortable with the caveats.
-
-For more details on ARC and exceptions:
-https://clang.llvm.org/docs/AutomaticReferenceCounting.html#exceptions
-
diff --git a/Documentation/Appendix.md b/Documents/Appendix.md
similarity index 69%
rename from Documentation/Appendix.md
rename to Documents/Appendix.md
index d3797f4d9..cf67c2504 100644
--- a/Documentation/Appendix.md
+++ b/Documents/Appendix.md
@@ -209,3 +209,45 @@ its work on a background thread.
Promises abstract asynchronicity, so exploit and support that model. Design your
APIs so that consumers don’t have to care what queue your functions run on.
+
+## `Dispatcher` Objects
+
+Some issues are best addressed at the level of dispatching. For example, you may need
+to perform a series of HTTP transactions on a server that allows only a certain number of
+API calls per minute. Or, you might want to allow only a certain number of memory-hungry
+background tasks to run at once. These aren't really promise-level concerns; they just have
+to do with the details of how closures are invoked once they become eligible to run.
+
+Unfortunately, `DispatchQueue`s don't directly support these types of restrictions, and because
+of the way `DispatchQueue` is implemented, you can't create your own subclasses. PromiseKit 7
+adds an abstract `Dispatcher` protocol that generalizes the idea of a dispatch queue and allows for
+alternate implementations:
+
+```swift
+public protocol Dispatcher {
+ func dispatch(_ body: @escaping () -> Void)
+}
+```
+
+Anywhere in PromiseKit that you can use a `DispatchQueue`, you're free to substitute a `Dispatcher`.
+
+PromiseKit doesn't care how you implement `dispatch()`. You can run the provided closure synchronously or
+asynchronously, now or at some point in the future, on any thread you wish. Of course, your own code
+must have a thread safety strategy and not create deadlocks.
+
+If you're setting a default dispatcher, assign your dispatcher to `PromiseKit.conf.D` rather than `PromiseKit.conf.Q`; the latter
+accepts only `DispatchQueue`s.
+
+**FIXME: Check locations and availability of Dispatcher implementations before release**
+
+A few handy `Dispatcher` types are available in the `Dispatchers` extension library:
+
+* `RateLimitedDispatcher` implements general dispatch rate limits with an approximate "token bucket" strategy.
+* `StrictRateLimitedDispatcher` is an exact and optimal "sliding window" rate limiter, but requires O(n) space (n = # of events/time)
+* `ConcurrencyLimitedDispatcher` allows only *n* asynchronous closures to run at once.
+* `CoreDataDispatcher` lets you dispatch onto threads associated with `NSManagedObjectContext`s.
+
+A couple of `Dispatcher`s are also included in the PromiseKit core:
+
+* `CurrentThreadDispatcher` runs closures immediately, on the current thread.
+* `DispatchQueueDispatcher` forwards to a `DispatchQueue`, applying a static `DispatchGroup`, quality of service, and flag set.
diff --git a/Documents/Cancel.md b/Documents/Cancel.md
new file mode 100644
index 000000000..3ee4943cb
--- /dev/null
+++ b/Documents/Cancel.md
@@ -0,0 +1,469 @@
+# Cancelling Promises
+
+PromiseKit 7 adds clear and concise cancellation abilities to promises and to the [PromiseKit extensions](#extensions-pane). Cancelling promises and their associated tasks is now simple and straightforward. Promises and promise chains can safely and efficiently be cancelled from any thread at any time.
+
+```swift
+UIApplication.shared.isNetworkActivityIndicatorVisible = true
+
+let fetchImage = URLSession.shared.dataTask(.promise, with: url)
+ .cancellize()
+ .compactMap{ UIImage(data: $0.data) }
+let fetchLocation = CLLocationManager.requestLocation().cancellize().lastValue
+
+let finalizer = firstly {
+ when(fulfilled: fetchImage, fetchLocation)
+}.done { image, location in
+ self.imageView.image = image
+ self.label.text = "\(location)"
+}.ensure {
+ UIApplication.shared.isNetworkActivityIndicatorVisible = false
+}.catch(policy: .allErrors) { error in
+ // `catch` will be invoked with `PMKError.cancelled` when cancel is called
+ // on the context. Use the default policy of `.allErrorsExceptCancellation`
+ // to ignore cancellation errors.
+ self.show(UIAlertController(for: error), sender: self)
+}
+
+//…
+
+// Cancel currently active tasks and reject all cancellable promises
+// with 'PMKError.cancelled'. `cancel()` can be called from any thread
+// at any time.
+finalizer.cancel()
+
+// `finalizer` here refers to the `CancellableFinalizer` for the chain.
+// Calling 'cancel' on any promise in the chain or on the finalizer
+// cancels the entire chain. Therefore calling `cancel` on the finalizer
+// cancels everything.
+```
+
+# Cancel Chains
+
+Promises can be cancelled using a `CancellablePromise`. The `cancellize()` method on `Promise` is used to convert a `Promise` into a `CancellablePromise`. If a promise chain is initialized with a `CancellablePromise`, then the entire chain is cancellable. Calling `cancel()` on any promise in the chain cancels the entire chain.
+
+Creating a chain where the entire chain can be cancelled is the recommended usage for cancellable promises.
+
+The `CancellablePromise` contains a `CancelContext` that keeps track of the tasks and promises for the chain. Promise chains can be cancelled either by calling the `cancel()` method on any `CancellablePromise` in the chain, or by calling `cancel()` on the `CancelContext` for the chain. It may be desirable to hold on to the `CancelContext` directly rather than a promise so that the promise can be deallocated by ARC when it is resolved.
+
+For example:
+
+```swift
+let context = firstly {
+ login()
+ /* The 'Thenable.cancellize' method initiates a cancellable promise chain by
+ returning a 'CancellablePromise'. */
+}.cancellize().then { creds in
+ fetch(avatar: creds.user)
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}.cancelContext
+
+// …
+
+/* Note: Promises can be cancelled using the 'cancel()' method on the 'CancellablePromise'.
+ However, it may be desirable to hold on to the 'CancelContext' directly rather than a
+ promise so that the promise can be deallocated by ARC when it is resolved. */
+context.cancel()
+```
+
+### Creating a partially cancellable chain
+
+A `CancellablePromise` can be placed at the start of a chain, but it cannot be embedded directly in the middle of a standard (non-cancellable) promise chain. Instead, a partially cancellable promise chain can be used. A partially cancellable chain is not the recommended way to use cancellable promises, although there may be cases where this is useful.
+
+**Convert a cancellable chain to a standard chain**
+
+`CancellablePromise` wraps a delegate `Promise`, which can be accessed with the `promise` property. The above example can be modified as follows so that once `login()` completes, the chain can no longer be cancelled:
+
+```swift
+/* Here, by calling 'promise.then' rather than 'then' the chain is converted from a cancellable
+ promise chain to a standard promise chain. In this example, calling 'cancel()' during 'login'
+ will cancel the chain but calling 'cancel()' during the 'fetch' operation will have no effect: */
+let cancellablePromise = firstly {
+ login().cancellize()
+}
+cancellablePromise.promise.then {
+ fetch(avatar: creds.user)
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+
+// …
+
+/* This will cancel the 'login' but will not cancel the 'fetch'. So whether or not the
+ chain is cancelled depends on how far the chain has progressed. */
+cancellablePromise.cancel()
+```
+
+**Convert a standard chain to a cancellable chain**
+
+A non-cancellable chain can be converted to a cancellable chain in the middle of the chain as follows:
+
+```swift
+/* In this example, calling 'cancel()' during 'login' will not cancel the login. However,
+ the chain will be cancelled immediately, and the 'fetch' will not be executed. If 'cancel()'
+ is called during the 'fetch' then both the 'fetch' itself and the promise chain will be
+ cancelled immediately. */
+let promise = firstly {
+ login()
+}.then {
+ fetch(avatar: creds.user).cancellize()
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+
+// …
+
+promise.cancel()
+```
+
+# Core Cancellable PromiseKit API
+
+The following classes, methods and functions have been added to PromiseKit to support cancellation. Existing functions or methods with underlying tasks that can be cancelled are indicated by being appended with '.cancellize()'.
+
+Thenable
+ cancellize(_:) - Converts the Promise or Guarantee (Thenable) into a
+ CancellablePromise, which is a cancellable variant of the given
+ Promise or Guarantee (Thenable)
+
+Global functions
+ after(seconds:).cancellize() - 'after' with seconds can be cancelled
+ after(_:).cancellize - 'after' with interval can be cancelled
+
+ firstly(execute:) - Accepts body returning Promise or CancellablePromise
+ hang(_:) - Accepts Promise and CancellablePromise
+ race(_:) - Accepts [Promise] and [CancellablePromise]
+ when(fulfilled:) - Accepts [Promise] and [CancellablePromise]
+ when(fulfilled:concurrently:) - Accepts iterator of type Promise or CancellablePromise
+ when(resolved:) - Accepts [Promise] and [CancellablePromise]
+
+CancellablePromise properties and methods
+ promise - Delegate Promise for this CancellablePromise
+ result - The current Result
+
+ init(_ bridge:cancelContext:) - Initialize a new cancellable promise bound to the provided Thenable
+ init(cancellable:resolver body:). - Initialize a new cancellable promise that can be resolved with
+ the provided '(Resolver) throws -> Void' body
+ init(cancellable:promise:resolver:) - Initialize a new cancellable promise using the given Promise
+ and its Resolver
+ init(cancellable:error:) - Initialize a new rejected cancellable promise
+ init(cancellable:) - Initializes a new cancellable promise fulfilled with Void
+
+ pending() -> (promise:resolver:) - Returns a tuple of a new cancellable pending promise and its
+ Resolver
+
+CancellableThenable properties and methods
+ thenable - Delegate Thenable for this CancellableThenable
+
+ cancel(error:) - Cancels all members of the promise chain
+ cancelContext - The CancelContext associated with this CancellableThenable
+ cancelItemList - Tracks the cancel items for this CancellableThenable
+ isCancelled - True if all members of the promise chain have been successfully
+ cancelled, false otherwise
+ cancelAttempted - True if 'cancel' has been called on the promise chain associated
+ with this CancellableThenable, false otherwise
+ cancelledError - The error generated when the promise is cancelled
+ appendCancellable(cancellable:reject:) - Append the Cancellable task to our cancel context
+ appendCancelContext(from:) - Append the cancel context associated with 'from' to our
+ CancelContext
+
+ then(on:flags:_ body:) - Accepts body returning CancellableThenable
+ cancellableThen(on:flags:_ body:) - Accepts body returning Thenable
+ map(on:flags:_ transform:)
+ compactMap(on:flags:_ transform:)
+ done(on:flags:_ body:)
+ get(on:flags:_ body:)
+ tap(on:flags:_ body:)
+ asVoid()
+
+ error
+ isPending
+ isResolved
+ isFulfilled
+ isRejected
+ value
+
+ mapValues(on:flags:_ transform:)
+ flatMapValues(on:flags:_ transform:)
+ compactMapValues(on:flags:_ transform:)
+ thenMap(on:flags:_ transform:) - Accepts transform returning CancellableThenable
+ cancellableThenMap(on:flags:_ transform:) - Accepts transform returning Thenable
+ thenFlatMap(on:flags:_ transform:) - Accepts transform returning CancellableThenable
+ cancellableThenFlatMap(on:flags:_ transform:) - Accepts transform returning Thenable
+ filterValues(on:flags:_ isIncluded:)
+ firstValue
+ lastValue
+ sortedValues(on:flags:)
+
+CancellableCatchable properties and methods
+ catchable - Delegate Catchable for this CancellableCatchable
+ catch(on:flags:policy::_ body:) - Accepts body returning Void
+ recover(on:flags:policy::_ body:) - Accepts body returning CancellableThenable
+ cancellableRecover(on:flags:policy::_ body:) - Accepts body returning Thenable
+ ensure(on:flags:_ body:) - Accepts body returning Void
+ ensureThen(on:flags:_ body:) - Accepts body returning CancellablePromise
+ finally(_ body:)
+ cauterize()
+
+
+# Extensions
+
+Cancellation support has been added to the PromiseKit extensions, but only where the underlying asynchronous tasks can be cancelled. This example Podfile lists the PromiseKit extensions that support cancellation along with a usage example:
+
+pod "PromiseKit/Alamofire"
+# Alamofire.request("http://example.com", method: .get).responseDecodable(DecodableObject.self).cancellize()
+
+pod "PromiseKit/Bolts"
+# CancellablePromise(…).then() { _ -> BFTask in /*…*/ } // Returns CancellablePromise
+
+pod "PromiseKit/CoreLocation"
+# CLLocationManager.requestLocation().cancellize().then { /*…*/ }
+
+pod "PromiseKit/Foundation"
+# URLSession.shared.dataTask(.promise, with: request).cancellize().then { /*…*/ }
+
+pod "PromiseKit/MapKit"
+# MKDirections(…).calculate().cancellize().then { /*…*/ }
+
+pod "PromiseKit/OMGHTTPURLRQ"
+# URLSession.shared.GET("http://example.com").cancellize().then { /*…*/ }
+
+pod "PromiseKit/StoreKit"
+# SKProductsRequest(…).start(.promise).cancellize().then { /*…*/ }
+
+pod "PromiseKit/SystemConfiguration"
+# SCNetworkReachability.promise().cancellize().then { /*…*/ }
+
+pod "PromiseKit/UIKit"
+# UIViewPropertyAnimator(…).startAnimation(.promise).cancellize().then { /*…*/ }
+
+
+Here is a complete list of PromiseKit extension methods that support cancellation:
+
+[Alamofire](http://github.com/PromiseKit/Alamofire-)
+
+Alamofire.DataRequest
+ response(_:queue:).cancellize()
+ responseData(queue:).cancellize()
+ responseString(queue:).cancellize()
+ responseJSON(queue:options:).cancellize()
+ responsePropertyList(queue:options:).cancellize()
+ responseDecodable(queue::decoder:).cancellize()
+ responseDecodable(_ type:queue:decoder:).cancellize()
+
+Alamofire.DownloadRequest
+ response(_:queue:).cancellize()
+ responseData(queue:).cancellize()
+
+
+[Bolts](http://github.com/PromiseKit/Bolts)
+
+CancellablePromise<T>
+ then<U>(on: DispatchQueue?, body: (T) -> BFTask<U>) -> CancellablePromise
+
+
+[CoreLocation](http://github.com/PromiseKit/CoreLocation)
+
+CLLocationManager
+ requestLocation(authorizationType:satisfying:).cancellize()
+ requestAuthorization(type requestedAuthorizationType:).cancellize()
+
+
+[Foundation](http://github.com/PromiseKit/Foundation)
+
+NotificationCenter:
+ observe(once:object:).cancellize()
+
+NSObject
+ observe(_:keyPath:).cancellize()
+
+Process
+ launch(_:).cancellize()
+
+URLSession
+ dataTask(_:with:).cancellize()
+ uploadTask(_:with:from:).cancellize()
+ uploadTask(_:with:fromFile:).cancellize()
+ downloadTask(_:with:to:).cancellize()
+
+CancellablePromise
+ validate()
+
+
+[HomeKit](http://github.com/PromiseKit/HomeKit)
+
+HMPromiseAccessoryBrowser
+ start(scanInterval:).cancellize()
+
+HMHomeManager
+ homes().cancellize()
+
+
+[MapKit](http://github.com/PromiseKit/MapKit)
+
+MKDirections
+ calculate().cancellize()
+ calculateETA().cancellize()
+
+MKMapSnapshotter
+ start().cancellize()
+
+
+[StoreKit](http://github.com/PromiseKit/StoreKit)
+
+SKProductsRequest
+ start(_:).cancellize()
+
+SKReceiptRefreshRequest
+ promise().cancellize()
+
+
+[SystemConfiguration](http://github.com/PromiseKit/SystemConfiguration)
+
+SCNetworkReachability
+ promise().cancellize()
+
+
+[UIKit](http://github.com/PromiseKit/UIKit)
+
+UIViewPropertyAnimator
+ startAnimation(_:).cancellize()
+
+
+## Choose Your Networking Library
+
+All the networking library extensions supported by PromiseKit are now simple to cancel!
+
+[Alamofire](http://github.com/PromiseKit/Alamofire-)
+
+```swift
+// pod 'PromiseKit/Alamofire'
+// # https://github.com/PromiseKit/Alamofire
+
+let context = firstly {
+ Alamofire
+ .request("http://example.com", method: .post, parameters: params)
+ .responseDecodable(Foo.self)
+}.cancellize().done { foo in
+ //…
+}.catch { error in
+ //…
+}.cancelContext
+
+//…
+
+context.cancel()
+```
+
+And (of course) plain `URLSession` from [Foundation](http://github.com/PromiseKit/Foundation):
+
+```swift
+// pod 'PromiseKit/Foundation'
+// # https://github.com/PromiseKit/Foundation
+
+let context = firstly {
+ URLSession.shared.dataTask(.promise, with: try makeUrlRequest())
+}.cancellize().map {
+ try JSONDecoder().decode(Foo.self, with: $0.data)
+}.done { foo in
+ //…
+}.catch { error in
+ //…
+}.cancelContext
+
+//…
+
+context.cancel()
+
+func makeUrlRequest() throws -> URLRequest {
+ var rq = URLRequest(url: url)
+ rq.httpMethod = "POST"
+ rq.addValue("application/json", forHTTPHeaderField: "Content-Type")
+ rq.addValue("application/json", forHTTPHeaderField: "Accept")
+ rq.httpBody = try JSONSerialization.jsonData(with: obj)
+ return rq
+}
+```
+
+# Cancellability Goals
+
+* Provide a streamlined way to cancel a promise chain, which rejects all associated promises and cancels all associated tasks. For example:
+
+```swift
+let promise = firstly {
+ login()
+}.cancellize().then { creds in // Use the 'cancellize' function to initiate a cancellable promise chain
+ fetch(avatar: creds.user)
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+//…
+promise.cancel()
+```
+
+* Ensure that subsequent code blocks in a promise chain are _never_ called after the chain has been cancelled
+
+* Fully support concurrency, where all code is thread-safe. Cancellable promises and promise chains can safely and efficiently be cancelled from any thread at any time.
+
+* Provide cancellable support for all PromiseKit extensions whose native tasks can be cancelled (e.g. Alamofire, Bolts, CoreLocation, Foundation, HealthKit, HomeKit, MapKit, StoreKit, SystemConfiguration, UIKit)
+
+* Support cancellation for all PromiseKit primitives such as 'after', 'firstly', 'when', 'race'
+
+* Provide a simple way to make new types of cancellable promises
+
+* Ensure promise branches are properly cancelled. For example:
+
+```swift
+import Alamofire
+import PromiseKit
+
+func updateWeather(forCity searchName: String) {
+ refreshButton.startAnimating()
+ let context = firstly {
+ getForecast(forCity: searchName)
+ }.cancellize().done { response in
+ updateUI(forecast: response)
+ }.ensure {
+ refreshButton.stopAnimating()
+ }.catch { error in
+ // Cancellation errors are ignored by default
+ showAlert(error: error)
+ }.cancelContext
+
+ //…
+
+ /* **** Cancels EVERYTHING (except... the 'ensure' block always executes regardless)
+ Note: non-cancellable tasks cannot be interrupted. For example: if 'cancel()' is
+ called in the middle of 'updateUI()' then the chain will immediately be rejected,
+ however the 'updateUI' call will complete normally because it is not cancellable.
+ Its return value (if any) will be discarded. */
+ context.cancel()
+}
+
+func getForecast(forCity name: String) -> CancellablePromise {
+ return firstly {
+ Alamofire.request("https://autocomplete.weather.com/\(name)")
+ .responseDecodable(AutoCompleteCity.self)
+ }.cancellize().then { city in
+ Alamofire.request("https://forecast.weather.com/\(city.name)")
+ .responseDecodable(WeatherResponse.self).cancellize()
+ }.map { response in
+ format(response)
+ }
+}
+```
diff --git a/Documentation/CommonPatterns.md b/Documents/CommonPatterns.md
similarity index 85%
rename from Documentation/CommonPatterns.md
rename to Documents/CommonPatterns.md
index 937a425f4..bcb0ff71a 100644
--- a/Documentation/CommonPatterns.md
+++ b/Documents/CommonPatterns.md
@@ -82,8 +82,10 @@ class MyRestAPI {
}
```
-All PromiseKit handlers take an `on` parameter that lets you designate the dispatch queue
-on which to run the handler. The default is always the main queue.
+All PromiseKit handlers take an `on` parameter that lets you designate a `Dispatcher` that
+will run the handler. Usually, the dispatcher is just a plain-vanilla `DispatchQueue`, but you
+can write your own if you like. The default is always `DispatchQueue.main`, which is a
+serial (nonconcurrent) queue.
PromiseKit is *entirely* thread safe.
@@ -212,22 +214,42 @@ one promise at a time if you need to.
```swift
let fetches: [Promise] = makeFetches()
-let timeout = after(seconds: 4)
-race(when(fulfilled: fetches).asVoid(), timeout).then {
+race(when(fulfilled: fetches).asVoid(), timeout(seconds: 4)).then {
//…
+}.catch(policy: .allErrors) {
+ // Rejects with 'PMKError.timedOut' if the timeout is exceeded
}
```
`race` continues as soon as one of the promises it is watching finishes.
+`timeout(seconds: TimeInterval)` returns a promise that throws
+`PMKError.timedOut` when the time interval is exceeded. Note that `PMKError.timedOut`
+is a cancellation error therefore the `.allErrors` catch policy must be specified
+to handle this exception.
+
Make sure the promises you pass to `race` are all of the same type. The easiest way
to ensure this is to use `asVoid()`.
Note that if any component promise rejects, the `race` will reject, too.
+When used with cancellable promises, all promises will be cancelled if either the timeout is
+exceeded or if any promise rejects.
+
+```swift
+let fetches: [Promise] = makeFetches()
+let cancellableFetches: [CancellablePromise] = fetches.map { return $0.cancellize() }
+
+// All promises are automatically cancelled if any of them reject.
+race(when(fulfilled: cancellableFetches).asVoid(), timeout(seconds: 4).cancellize()).then {
+ //…
+}.catch(policy: .allErrors) {
+ // Rejects with 'PMKError.timedOut' if the timeout is exceeded.
+}
+```
-# Minimum Duration
+## Minimum Duration
Sometimes you need a task to take *at least* a certain amount of time. (For example,
you want to show a progress spinner, but if it shows for less than 0.3 seconds, the UI
@@ -245,61 +267,22 @@ firstly {
}
```
-The code above works because we create the delay *before* we do work in `foo()`. By the
+The code above works because we create the delay *before* we do work in `foo()`. By the
time we get to waiting on that promise, either it will have already timed out or we will wait
for whatever remains of the 0.3 seconds before continuing the chain.
## Cancellation
-Promises don’t have a `cancel` function, but they do support cancellation through a
-special error type that conforms to the `CancellableError` protocol.
-
-```swift
-func foo() -> (Promise, cancel: () -> Void) {
- let task = Task(…)
- var cancelme = false
-
- let promise = Promise { seal in
- task.completion = { value in
- guard !cancelme else { return reject(PMKError.cancelled) }
- seal.fulfill(value)
- }
- task.start()
- }
-
- let cancel = {
- cancelme = true
- task.cancel()
- }
-
- return (promise, cancel)
-}
-```
-
-Promises don’t have a `cancel` function because you don’t want code outside of
-your control to be able to cancel your operations--*unless*, of course, you explicitly
-want to enable that behavior. In cases where you do want cancellation, the exact way
-that it should work will vary depending on how the underlying task supports cancellation.
-PromiseKit provides cancellation primitives but no concrete API.
-
-Cancelled chains do not call `catch` handlers by default. However you can
-intercept cancellation if you like:
+Starting with version 7, PromiseKit explicitly supports cancellation of promises and
+promise chains. There is a new class called `CancellablePromise` that defines a `cancel`
+method. Use the `cancellize` method on `Thenable` to obtain a `CancellablePromise` from a
+`Promise` or `Guarantee`.
-```swift
-foo.then {
- //…
-}.catch(policy: .allErrors) {
- // cancelled errors are handled *as well*
-}
-```
-
-**Important**: Canceling a promise chain is *not* the same as canceling the underlying
-asynchronous task. Promises are wrappers around asynchronicity, but they have no
-control over the underlying tasks. If you need to cancel an underlying task, you
-need to cancel the underlying task!
+Invoking `cancel` will both reject the promise with `PMKError.cancelled` and cancel any
+underlying asynchronous task(s).
-> The library [CancellablePromiseKit](https://github.com/johannesd/CancellablePromiseKit) extends the concept of Promises to fully cover cancellable tasks.
+For full details see [Cancelling Promises](Cancel.md).
## Retry / Polling
@@ -483,7 +466,7 @@ Use `when(resolved:)`:
```swift
when(resolved: a, b).done { (results: [Result]) in
- // `Result` is an enum of `.fulfilled` or `.rejected`
+ //…
}
// ^^ cannot call `catch` as `when(resolved:)` returns a `Guarantee`
diff --git a/Documentation/Examples/ImageCache.md b/Documents/Examples/ImageCache.md
similarity index 100%
rename from Documentation/Examples/ImageCache.md
rename to Documents/Examples/ImageCache.md
diff --git a/Documentation/Examples/URLSession+BadResponseErrors.swift b/Documents/Examples/URLSession+BadResponseErrors.swift
similarity index 100%
rename from Documentation/Examples/URLSession+BadResponseErrors.swift
rename to Documents/Examples/URLSession+BadResponseErrors.swift
diff --git a/Documentation/Examples/detweet.swift b/Documents/Examples/detweet.swift
similarity index 100%
rename from Documentation/Examples/detweet.swift
rename to Documents/Examples/detweet.swift
diff --git a/Documentation/FAQ.md b/Documents/FAQ.md
similarity index 85%
rename from Documentation/FAQ.md
rename to Documents/FAQ.md
index decd7ba3d..a6222cf91 100644
--- a/Documentation/FAQ.md
+++ b/Documents/FAQ.md
@@ -8,7 +8,7 @@
* Do you want a library that has been maintained continuously and passionately for 6 years? Then pick PromiseKit.
* Do you want a library that the community has chosen to be their №1 Promises/Futures library? Then pick PromiseKit.
* Do you want to be able to use Promises with Apple’s SDKs rather than having to do all the work of writing the Promise implementations yourself? Then pick PromiseKit.
-* Do you want to be able to use Promises with Swift 3.x, Swift 4.x, ObjC, iOS, tvOS, watchOS, macOS, Android & Linux? Then pick PromiseKit.
+* Do you want to be able to use Promises with Swift, ObjC, iOS, tvOS, watchOS, macOS, Android & Linux? Then pick PromiseKit.
* PromiseKit verifies its correctness by testing against the entire [Promises/A+ test suite](https://github.com/promises-aplus/promises-tests).
## How do I create a fulfilled `Void` promise?
@@ -229,8 +229,8 @@ So, RxSwift tries hard to supply every operator you might ever want to use right
hundreds. PromiseKit supplies a few utilities to help with specific scenarios, but because it's trivial
to write your own chain elements, there's no need for all this extra code in the library.
-* PromiseKit dispatches the execution of every block. RxSwift dispatches only when told to do so. Moreover, the
-current dispatching state is an attribute of the chain, not the specific block, as it is in PromiseKit.
+* PromiseKit dispatches the execution of every block. RxSwift dispatches only when told to do so. Moreover,
+in RxSwift, the current dispatching state is an attribute of the chain, not the specific block, as it is in PromiseKit.
The RxSwift system is more powerful but more complex. PromiseKit is simple, predictable and safe.
* In PromiseKit, both sides of a branched chain refer back to their shared common ancestors. In RxSwift,
@@ -317,36 +317,56 @@ feature because it gives you guarantees about the flow of your chains.
## How do I change the default queues that handlers run on?
-You can change the values of `PromiseKit.conf.Q`. There are two variables that
-change the default queues that the two kinds of handler run on. A typical
-pattern is to change all your `then`-type handlers to run on a background queue
+You can change the values of `PromiseKit.conf.Q` or `PromiseKit.conf.D`. These
+variables both access the same underlying state. However, `conf.Q` presents it in terms of
+`DispatchQueue`s, while `conf.D` presents it in terms of the more general
+`Dispatcher`-protocol objects that PromiseKit uses internally. (`DispatchQueue`s are
+just one possible implementation of `Dispatcher`, although they are the ones that account
+for nearly all actual use.)
+
+Each of these configuration variables is a two-tuple that identifies two separate dispatchers named `map` and `return`.
+
+```swift
+public var Q: (map: DispatchQueue?, return: DispatchQueue?)
+public var D: (map: Dispatcher, return: Dispatcher)
+```
+
+The `return` dispatcher is the default for chain-finalizing methods such as `done`
+and `catch`. The `map` dispatcher is the default for everything else. A
+typical pattern is to change all your `then`-type handlers to run on a background queue
and to have all your “finalizers” run on the main queue:
```
PromiseKit.conf.Q.map = .global()
-PromiseKit.conf.Q.return = .main //NOTE this is the default
+PromiseKit.conf.Q.return = .main
```
-Be very careful about setting either of these queues to `nil`. It has the
-effect of running *immediately*, and this is not what you usually want to do in
-your application. This is, however, useful when you are running specs and want
-your promises to resolve immediately. (This is basically the same idea as "stubbing"
-an HTTP request.)
+Note that `DispatchQueue.main` is the default for _both_ dispatchers.
+
+Be very careful about setting either part of `conf.Q` to `nil`. It has the
+effect of running closures *immediately*, and this is not what you usually want to do in
+your application. It is useful, however, when you are running specs and want
+your promises to resolve immediately. (It's basically the same idea as "stubbing"
+HTTP requests.)
```swift
// in your test suite setup code
-PromiseKit.conf.Q.map = nil
-PromiseKit.conf.Q.return = nil
+PromiseKit.conf.Q = (map: nil, return: nil)
```
## How do I use PromiseKit on the server side?
If your server framework requires that the main queue remain unused (e.g., Kitura),
-then you must use PromiseKit 6 and you must tell PromiseKit not to dispatch to the
-main queue by default. This is easy enough:
+then you must tell PromiseKit not to dispatch there by default. This is easy enough:
+
+```swift
+PromiseKit.conf.Q = (map: .global(), return: .global())
+```
+If you want to emulate the serializing behavior of `DispatchQueue.main`, just create and label
+a new `DispatchQueue`. It'll be serial by default.
```swift
-PromiseKit.conf.Q = (map: DispatchQueue.global(), return: DispatchQueue.global())
+PromiseKit.conf.Q.return = DispatchQueue(label: "virtual main queue")
```
> Note, we recommend using your own queue rather than `.global()`, we've seen better performance this way.
@@ -382,12 +402,12 @@ Kitura.run()
## How do I control console output?
-By default PromiseKit emits console messages when certain events occur. These events include:
+By default, PromiseKit emits warning messages on the console when certain events occur. These events include:
- A promise or guarantee has blocked the main thread
- A promise has been deallocated without being fulfilled
- An error which occurred while fulfilling a promise was swallowed using cauterize
-You may turn off or redirect this output by setting a thread safe closure in [PMKConfiguration](https://github.com/mxcl/PromiseKit/blob/master/Sources/Configuration.swift) **before** processing any promises. For example, to turn off console output:
+You may turn off or redirect this output by setting a thread-safe closure in [PMKConfiguration](https://github.com/mxcl/PromiseKit/blob/master/Sources/Configuration.swift) **before** processing any promises. For example, to turn off console output:
```swift
conf.logHandler = { event in }
diff --git a/Documentation/GettingStarted.md b/Documents/GettingStarted.md
similarity index 91%
rename from Documentation/GettingStarted.md
rename to Documents/GettingStarted.md
index 8f6af48dc..2e5bb61c4 100644
--- a/Documentation/GettingStarted.md
+++ b/Documents/GettingStarted.md
@@ -32,7 +32,7 @@ readability. The promise chain above is easy to scan and understand: one asynchr
operation leads into the other, line by line. It's as close to
procedural code as we can easily come given the current state of Swift.
-`done` is the same as `then` but you cannot return a promise. It is
+`done` is the same as `then` but you cannot return a promise. It is
typically the end of the “success” part of the chain. Above, you can see that we
receive the final image in our `done` and use it to set up the UI.
@@ -40,15 +40,15 @@ Let’s compare the signatures of the two login methods:
```swift
func login() -> Promise
-
+
// Compared with:
func login(completion: (Creds?, Error?) -> Void)
// ^^ ugh. Optionals. Double optionals.
```
-The distinction is that with promises, your functions return *promises* instead
-of accepting and running callbacks. Each handler in a chain returns a promise.
+The distinction is that with promises, your functions return *promises* instead
+of accepting and running callbacks. Each handler in a chain returns a promise.
`Promise` objects define the `then` method, which waits for the completion of the
promise before continuing the chain. Chains resolve procedurally, one promise
at a time.
@@ -58,9 +58,9 @@ that represents the type of object it wraps. For example, in the example above,
`login` is a function that returns a `Promise` that *will* represent an instance
of `Creds`.
-> *Note*: `done` is new to PromiseKit 5. We previously defined a variant of `then` that
+> *Note*: `done` was introduced in PromiseKit 5. We previously defined a variant of `then` that
did not require you to return a promise. Unfortunately, this convention often confused
-Swift and led to odd and hard-to-debug error messages. It also made using PromiseKit
+Swift and led to odd and hard-to-debug error messages. It also made using PromiseKit
more painful. The introduction of `done` lets you type out promise chains that
compile without additional qualification to help the compiler figure out type information.
@@ -158,9 +158,9 @@ login { creds, error in
}
```
-It would be very easy for someone to amend this code and forget to unset
+It would be very easy for someone to amend this code and forget to unset
the activity indicator, leading to a bug. With promises, this type of error is
-almost impossible: the Swift compiler resists your supplementing the chain without
+almost impossible: the Swift compiler resists your supplementing the chain without
using promises. You almost won’t need to review the pull requests.
> *Note*: PromiseKit has perhaps capriciously switched between the names `always`
@@ -234,7 +234,7 @@ As with any promise chain, if any of the component promises fail, the chain call
# PromiseKit Extensions
-When we made PromiseKit, we understood that we wanted to use *only* promises to implement
+When we made PromiseKit, we understood that we wanted to use *only* promises to implement
asynchronous behavior. So wherever possible, we offer extensions to Apple’s APIs that reframe
the API in terms of promises. For example:
@@ -256,12 +256,7 @@ pod "PromiseKit/CoreLocation"
pod "PromiseKit/MapKit"
```
-All of these extensions are available at the [PromiseKit organization](https://github.com/PromiseKit).
-Go there to see what's available and to read the source code and documentation. Every file and function
-has been copiously documented.
-
-> We also provide extensions for common libraries such as [Alamofire](https://github.com/PromiseKit/Alamofire-).
-
+To see what is available, check our [sources](https://github.com/mxcl/PromiseKit/tree/master/Sources).
# Making Promises
@@ -296,9 +291,9 @@ func fetch() -> Promise {
}
```
-The `seal` object that the `Promise` initializer provides to you defines
-many methods for handling garden-variety completion handlers. It even
-covers a variety of rarer situations, thus making it easy for you to add
+The `seal` object that the `Promise` initializer provides to you defines
+many methods for handling garden-variety completion handlers. It even
+covers a variety of rarer situations, thus making it easy for you to add
promises to an existing codebase.
> *Note*: We tried to make it so that you could just do `Promise(fetch)`, but we
@@ -311,10 +306,10 @@ extra disambiguation for the Swift compiler. Sorry; we tried.
typically just pass completion handler parameters to `resolve` and let Swift figure
out which variant to apply to your particular case (as shown in the example above).
-> *Note* `Guarantees` (below) have a slightly different initializer (since they
-cannot error) so the parameter to the initializer closure is just a closure. Not
-a `Resolver` object. Thus do `seal(value)` rather than `seal.fulfill(value)`. This
-is because there is no variations in what guarantees can be sealed with, they can
+> *Note*: `Guarantee`s (below) have a slightly different initializer since they
+cannot error, so the parameter to the initializer closure is just a closure. Not
+a `Resolver` object. Just do `seal(value)` rather than `seal.fulfill(value)`. It's
+different because there is only one way to seal guarantees; they can
*only* fulfill.
# `Guarantee`
@@ -333,8 +328,8 @@ firstly {
```
Swift warns you if you don’t terminate a regular `Promise` chain (i.e., not
-a `Guarantee` chain). You're expected to silence this warning by supplying
-either a `catch` or a `return`. (In the latter case, you will then have to `catch`
+a `Guarantee` chain). You're expected to silence this warning by supplying
+either a `catch` or a `return`. (In the latter case, you will then have to `catch`
at the point where you receive that promise.)
Use `Guarantee`s wherever possible so that your code has error handling where
@@ -346,7 +341,7 @@ if you find an issue.
---
-If you are creating your own guarantees the syntax is simpler than that of promises;
+If you are creating your own guarantees the syntax is simpler than that of promises:
```swift
func fetch() -> Promise {
@@ -471,12 +466,12 @@ Here is a key understanding: `login()` returns a `Promise`, and all `Promise`s h
`when` is one of PromiseKit’s more useful functions, and so we offer several variants.
* The default `when`, and the one you should typically use, is `when(fulfilled:)`. This variant
-waits on all its component promises, but if any fail, `when` fails too, and thus the chain *rejects*.
+waits on all its component promises, but if any fail, `when` fails too, and thus the chain *rejects*.
It's important to note that all promises in the `when` *continue*. Promises have *no* control over
the tasks they represent. Promises are just wrappers around tasks.
* `when(resolved:)` waits even if one or more of its component promises fails. The value produced
-by this variant of `when` is an array of `Result`. Consequently, this variant requires all its
+by this variant of `when` is an array of `Result`. Consequently, this variant requires all its
component promises to have the same generic type. See our advanced patterns guide for work-arounds
for this limitation.
@@ -507,7 +502,7 @@ However, this shorthand is both a blessing and a curse. You may find that the Sw
often fails to infer return types properly. See our [Troubleshooting Guide](Troubleshooting.md) if
you require further assistance.
-> By adding `done` to PromiseKit 5, we have managed to avoid many of these common
+> By adding `done` to PromiseKit 5, we were able to blunt many of these common
pain points in using PromiseKit and Swift.
@@ -527,9 +522,9 @@ Here are some recent articles that document PromiseKit 5+:
* [Using Promises - Agostini.tech](https://agostini.tech/2018/10/08/using-promisekit)
-Careful with general online references, many of them refer to PMK < 5 which has a subtly
-different API (sorry about that, but Swift has changed a lot over the years and thus
-we had to too).
+Be careful when consulting general online references, as many of them refer to PMK < 5, which has a subtly
+different API. (Sorry about that, but Swift has changed a lot over the years and thus
+we had to as well.)
-[API Reference]: https://mxcl.dev/PromiseKit/reference/v6/Classes/Promise.html
+[API Reference]: https://mxcl.dev/PromiseKit/reference/v7/Classes/Promise.html
diff --git a/Documents/Installation.md b/Documents/Installation.md
new file mode 100644
index 000000000..8f51add0b
--- /dev/null
+++ b/Documents/Installation.md
@@ -0,0 +1,38 @@
+# Installing PromiseKit
+
+We support [SwiftPM]:
+
+```swift
+package.dependencies.append(
+ .package(url: "https://github.com/mxcl/PromiseKit", from: "7.0.0-rc1")
+)
+
+package.targets.append(
+ .target(name: "…", dependencies: [
+ .product(name: "PromiseKit", package: "PromiseKit"),
+ .product(name: "PMKFoundation", package: "PromiseKit"),
+ .product(name: "PMKMapKit", package: "PromiseKit"),
+ ])
+)
+```
+
+And CocoaPods:
+
+> Please note, we have not released this CocoaPod yet. You *can* still use it
+> but you will need to specify the podspec URL manually, see the Cocoapods docs.
+
+```ruby
+pod "PromiseKit", "~> 7.0.0-rc1"
+pod "PromiseKit/Foundation", "~> 7.0.0-rc1"
+pod "PromiseKit/MapKit", "~> 7.0.0-rc1"
+```
+
+## Carthage
+
+We will support [Carthage] if you can PR an automated solution for generating
+the `.xcodeproj` on release. It will need to support all our extensions.
+
+
+[SwiftPM]: https://swift.org/package-manager
+[CocoaPods]: https://cocoapods.org
+[Carthage]: https://github.com/Carthage/Carthage
diff --git a/Documentation/README.md b/Documents/README.md
similarity index 76%
rename from Documentation/README.md
rename to Documents/README.md
index a03f4aa42..2560462ee 100644
--- a/Documentation/README.md
+++ b/Documents/README.md
@@ -4,11 +4,11 @@
* Handbook
* [Getting Started](GettingStarted.md)
* [Promises: Common Patterns](CommonPatterns.md)
+ * [Cancelling Promises](Cancel.md)
* [Frequently Asked Questions](FAQ.md)
* Manual
* [Installation Guide](Installation.md)
- * [Objective-C Guide](ObjectiveC.md)
* [Troubleshooting](Troubleshooting.md)
* [Appendix](Appendix.md)
* [Examples](Examples)
-* [API Reference](https://mxcl.dev/PromiseKit/reference/v6/Classes/Promise.html)
+* [API Reference](https://mxcl.dev/PromiseKit/reference/v7/Classes/Promise.html)
diff --git a/Documentation/Troubleshooting.md b/Documents/Troubleshooting.md
similarity index 63%
rename from Documentation/Troubleshooting.md
rename to Documents/Troubleshooting.md
index 1e38b2676..37cba295a 100644
--- a/Documentation/Troubleshooting.md
+++ b/Documents/Troubleshooting.md
@@ -24,7 +24,7 @@ What’s the real problem? `then` *must* return a `Promise`, and you're trying t
```swift
return firstly {
- URLSession.shared.dataTask(.promise, with: url)
+ URLSession.shared.dataTask(.promise, with: url)
}.compactMap {
JSONSerialization.jsonObject(with: $0.data) as? [String: Any]
}.map { dict in
@@ -68,7 +68,7 @@ return firstly {
}
```
-We have made great effort to reduce the need for explicit typing in PromiseKit 6,
+We have made great effort to reduce the need for explicit typing in PromiseKit,
but as with all Swift functions that return a generic type (e.g., `Array.map`),
you may need to explicitly tell Swift what a closure returns if the closure's body is
longer than one line.
@@ -163,6 +163,131 @@ An *inline* function like this is all you need. Here, the problem is that you
forgot to mark the last line of the closure with an explicit `return`. It's required
here because the closure is longer than one line.
+### Cancellable promise embedded in the middle of a standard promise chain
+
+Error: ***Cannot convert value of type 'Promise<>' to closure result type 'Guarantee<>'***. Fixed by adding `cancellize` to `firstly { login() }`.
+
+```swift
+/// 'login()' returns 'Promise'
+/// 'fetch(avatar:)' returns 'CancellablePromise'
+
+let promise = firstly {
+ login() /// <-- ERROR: Cannot convert value of type 'Promise' to closure result type 'Guarantee'
+}.then { creds in /// CHANGE TO: "}.cancellize().then { creds in"
+ fetch(avatar: creds.user) /// <-- ERROR: Cannot convert value of type 'CancellablePromise' to
+ /// closure result type 'Guarantee'
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+
+// …
+
+promise.cancel()
+```
+
+### The return type for a multi-line closure returning `CancellablePromise` is not explicitly stated
+
+The Swift compiler cannot (yet) determine the return type of a multi-line closure.
+
+The following example gives the unhelpful error: ***'()' is not convertible to 'UIImage'***. Many other strange errors can result from not explicitly declaring the return type of a multi-line closure. These kinds of errors are fixed by explicitly declaring the return type, which in the following example is a `CancellablePromise``.
+
+```swift
+/// 'login()' returns 'Promise'
+/// 'fetch(avatar:)' returns 'CancellablePromise'
+
+let promise = firstly {
+ login()
+}.cancellize().then { creds in /// CHANGE TO: "}.cancellize().then { creds -> CancellablePromise in"
+ let f = fetch(avatar: creds.user)
+ return f
+}.done { image in
+ self.imageView = image /// <-- ERROR: '()' is not convertible to 'UIImage'
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+
+// …
+
+promise.cancel()
+```
+
+### Trying to cancel a standard promise chain
+
+Error: ***Value of type `PMKFinalizer` has no member `cancel`***. Fixed by using cancellable promises instead of standard promises.
+
+```swift
+/// 'login()' returns 'Promise'
+/// 'fetch(avatar:)' returns 'CancellablePromise'
+
+let promise = firstly {
+ login()
+}.then { creds in /// CHANGE TO: "}.cancellize().then { creds in"
+ fetch(avatar: creds.user).promise /// CHANGE TO: fetch(avatar: creds.user)
+}.done { image in
+ self.imageView = image
+}.catch(policy: .allErrors) { error in
+ if error.isCancelled {
+ // the chain has been cancelled!
+ }
+}
+
+// …
+
+promise.cancel() /// <-- ERROR: Value of type 'PMKFinalizer' has no member 'cancel'
+```
+
+### Compilation for long chains is very slow or times out, especially with cancellable promises
+
+If a cancellable promise chain has more than a few (> 3) calls to `thenMap` and
+`thenFlatMap` or has an extensive number of calls in the chain (> 6), you
+may need to specify the return types for all closures in the chain. Standard
+(non-cancellable) promise chains typically only see this problem if they are
+extremely long (> 15 calls).
+
+And if compilation with promises is generally sluggish, the time may be greatly
+improved by specifying return types for all closures.
+
+For example:
+
+```swift
+/// Compilation timeout error:
+Promise.value([42, 52]).cancellize().then {
+ Promise.value($0)
+}.then {
+ Promise.value($0)
+}.thenMap {
+ Promise.value($0 + 10).cancellize()
+}.thenMap {
+ Promise.value($0 + 10)
+}.thenFlatMap {
+ Promise.value([$0 + 10]).cancellize()
+}.thenFlatMap { /// <-- Error: The compiler is unable to type-check this expression
+ /// in reasonable time; try breaking up the expression
+ /// into distinct sub-expressions
+ Promise.value([$0 + 10])
+}
+
+/// Compiles very quickly:
+Promise.value([42, 52]).cancellize().then { v -> Promise<[Int]> in
+ Promise.value(v)
+}.then { v -> Promise<[Int]> in
+ Promise.value(v)
+}.thenMap { v -> CancellablePromise in
+ Promise.value(v + 10).cancellize()
+}.thenMap { v -> Promise in
+ Promise.value(v + 10)
+}.thenFlatMap { v -> CancellablePromise<[Int]> in
+ Promise.value([v + 10]).cancellize()
+}.thenFlatMap { v -> Promise<[Int]> in
+ Promise.value([v + 10])
+}
+```
## You copied code off the Internet that doesn’t work
@@ -175,17 +300,17 @@ All PromiseKit functions are documented and provide examples.
You have a `then`; you want a `done`.
-## "Missing argument for parameter #1 in call"
+## "Missing argument for parameter #1 in call" "Unable to infer closure type in the current context"
This is part of Swift 4’s “tuplegate”.
-You must specify your `Void` parameter:
+You must fulfill a `Promise` with an explicit `Void` parameter:
```swift
seal.fulfill(())
```
-Yes: we hope they revert this change in Swift 5 too.
+This wart remains in Swift 5, too. It's probably not going to change.
## "Ambiguous reference to 'firstly(execute:)'"
diff --git a/Extensions/AVFoundation b/Extensions/AVFoundation
deleted file mode 160000
index 911b25778..000000000
--- a/Extensions/AVFoundation
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 911b257783efc0aa705481d556c8ecdfcdc055a9
diff --git a/Extensions/Accounts b/Extensions/Accounts
deleted file mode 160000
index 6c01f5719..000000000
--- a/Extensions/Accounts
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6c01f5719ff08bbbf81d42b7e20c5188cab4a81d
diff --git a/Extensions/AddressBook b/Extensions/AddressBook
deleted file mode 160000
index c694fa062..000000000
--- a/Extensions/AddressBook
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit c694fa0628a96951c6e2db113dc4eb6dd4e47ebc
diff --git a/Extensions/Alamofire b/Extensions/Alamofire
deleted file mode 160000
index a41a97d3d..000000000
--- a/Extensions/Alamofire
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit a41a97d3d3aa6efb575d0f42f3b8aeec5a756ead
diff --git a/Extensions/AssetsLibrary b/Extensions/AssetsLibrary
deleted file mode 160000
index e4317d527..000000000
--- a/Extensions/AssetsLibrary
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e4317d5279db7ecfc5bc565e1dd88fcabc02c352
diff --git a/Extensions/Bolts b/Extensions/Bolts
deleted file mode 160000
index fbc994121..000000000
--- a/Extensions/Bolts
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit fbc9941219c9bbdfe6d664ca6b8d10b5e2f8fb70
diff --git a/Extensions/CloudKit b/Extensions/CloudKit
deleted file mode 160000
index 9586f3c06..000000000
--- a/Extensions/CloudKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9586f3c06c4934e776c2b96c128f332a168c2c91
diff --git a/Extensions/CoreBluetooth b/Extensions/CoreBluetooth
deleted file mode 160000
index 8e0bc9579..000000000
--- a/Extensions/CoreBluetooth
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 8e0bc957996daad5c49f8809839f8699883ed364
diff --git a/Extensions/CoreLocation b/Extensions/CoreLocation
deleted file mode 160000
index c4ea4dba6..000000000
--- a/Extensions/CoreLocation
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit c4ea4dba6e0516986b3cb1d93c86f6991ce46861
diff --git a/Extensions/EventKit b/Extensions/EventKit
deleted file mode 160000
index 1f90d6753..000000000
--- a/Extensions/EventKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 1f90d67538047087428d82550976c2e43aba0961
diff --git a/Extensions/Foundation b/Extensions/Foundation
deleted file mode 160000
index 1a276e598..000000000
--- a/Extensions/Foundation
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 1a276e598dac59489ed904887e0740fa75e571e0
diff --git a/Extensions/HealthKit b/Extensions/HealthKit
deleted file mode 160000
index b185822cb..000000000
--- a/Extensions/HealthKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit b185822cb1fcf5297347498b783b4e21b2e55282
diff --git a/Extensions/HomeKit b/Extensions/HomeKit
deleted file mode 160000
index 668abe78a..000000000
--- a/Extensions/HomeKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 668abe78a52a23bd276c8924dba91592ac0ca45a
diff --git a/Extensions/MapKit b/Extensions/MapKit
deleted file mode 160000
index d1d4ebdd6..000000000
--- a/Extensions/MapKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d1d4ebdd6ceac78d734e2ae27e8ab429906d6929
diff --git a/Extensions/MessagesUI b/Extensions/MessagesUI
deleted file mode 160000
index 2a93ce737..000000000
--- a/Extensions/MessagesUI
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 2a93ce737502e13a3eaedc444b9ecb5abb28ec79
diff --git a/Extensions/OMGHTTPURLRQ b/Extensions/OMGHTTPURLRQ
deleted file mode 160000
index 5ec40a68f..000000000
--- a/Extensions/OMGHTTPURLRQ
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 5ec40a68f168255dcc339b9620e2dcf62079ae6b
diff --git a/Extensions/Photos b/Extensions/Photos
deleted file mode 160000
index 48f801454..000000000
--- a/Extensions/Photos
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 48f801454b01c69a1553873cb1d95e90ae2ec4cc
diff --git a/Extensions/QuartzCore b/Extensions/QuartzCore
deleted file mode 160000
index b22f187b6..000000000
--- a/Extensions/QuartzCore
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit b22f187b6b3f82f102aa309b256bf24570a73d1f
diff --git a/Extensions/Social b/Extensions/Social
deleted file mode 160000
index 378912a47..000000000
--- a/Extensions/Social
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 378912a47a206183b931d2008e0f396e9fc390e8
diff --git a/Extensions/StoreKit b/Extensions/StoreKit
deleted file mode 160000
index e26f6a559..000000000
--- a/Extensions/StoreKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e26f6a55921ea671855093754686991b08ef97cc
diff --git a/Extensions/SystemConfiguration b/Extensions/SystemConfiguration
deleted file mode 160000
index 6b009f906..000000000
--- a/Extensions/SystemConfiguration
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6b009f906fc489346a73759b5668b263a320c51c
diff --git a/Extensions/UIKit b/Extensions/UIKit
deleted file mode 160000
index baf104ba2..000000000
--- a/Extensions/UIKit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit baf104ba29ff94d9d41e90e8ec557a56b87fecd4
diff --git a/Extensions/WatchConnectivity b/Extensions/WatchConnectivity
deleted file mode 160000
index b5b3fca95..000000000
--- a/Extensions/WatchConnectivity
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit b5b3fca958a7296f71313b6c172584bc91d6da8b
diff --git a/Package.resolved b/Package.resolved
new file mode 100644
index 000000000..3e3af447c
--- /dev/null
+++ b/Package.resolved
@@ -0,0 +1,16 @@
+{
+ "object": {
+ "pins": [
+ {
+ "package": "OHHTTPStubs",
+ "repositoryURL": "https://github.com/AliSoftware/OHHTTPStubs",
+ "state": {
+ "branch": null,
+ "revision": "12f19662426d0434d6c330c6974d53e2eb10ecd9",
+ "version": "9.1.0"
+ }
+ }
+ ]
+ },
+ "version": 1
+}
diff --git a/Package.swift b/Package.swift
index d96717491..4159af2b3 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,30 +1,65 @@
-// swift-tools-version:4.0
+// swift-tools-version:5.3
import PackageDescription
let pkg = Package(name: "PromiseKit")
-pkg.products = [
- .library(name: "PromiseKit", targets: ["PromiseKit"]),
+pkg.platforms = [
+ .macOS(.v10_10),
+ .iOS(.v10), //FIXME strictly 8.0, but Tests require 10
+ .tvOS(.v10), //FIXME strictly 9.0, but Tests require 10
+ .watchOS(.v3)
]
+pkg.swiftLanguageVersions = [.v5]
-let pmk: Target = .target(name: "PromiseKit")
-pmk.path = "Sources"
-pmk.exclude = [
- "AnyPromise.swift",
- "AnyPromise.m",
- "PMKCallVariadicBlock.m",
- "dispatch_promise.m",
- "join.m",
- "when.m",
- "NSMethodSignatureForBlock.m",
- "after.m",
- "hang.m",
- "race.m",
- "Deprecations.swift"
+#if !os(Linux) && !os(Windows)
+pkg.dependencies = [
+ .package(url: "https://github.com/AliSoftware/OHHTTPStubs", from: "9.1.0")
]
-pkg.swiftLanguageVersions = [3, 4, 5]
-pkg.targets = [
- pmk,
- .testTarget(name: "APlus", dependencies: ["PromiseKit"], path: "Tests/A+"),
- .testTarget(name: "CorePromise", dependencies: ["PromiseKit"], path: "Tests/CorePromise"),
+#endif
+
+func dependencies(for name: String) -> [Target.Dependency] {
+ switch name {
+ case "PromiseKit":
+ return []
+ default:
+ return [.target(name: "PromiseKit")]
+ }
+}
+
+func has(tests name: String) -> Target? {
+ switch name {
+ case "PMKFoundation":
+ var deps = [Target.Dependency.target(name: "PMKFoundation")]
+ #if !os(Linux) && !os(Windows)
+ deps.append(.product(name: "OHHTTPStubsSwift", package: "OHHTTPStubs"))
+ #endif
+ return .testTarget(name: "\(name)Tests", dependencies: deps, path: "Tests/\(name)")
+ case "PMKHomeKit", "PMKMapKit", "PMKCoreLocation":
+ return .testTarget(name: "\(name)Tests", dependencies: [.target(name: name)], path: "Tests/\(name)")
+ default:
+ return nil
+ }
+}
+
+for name in ["PMKCloudKit", "PMKCoreLocation", "PMKFoundation", "PMKHealthKit", "PMKHomeKit", "PMKMapKit", "PMKPhotos", "PMKStoreKit", "PromiseKit"] {
+
+ #if os(Linux) || os(Windows)
+ guard name == "PromiseKit" || name == "PMKFoundation" else { continue }
+ #endif
+
+ pkg.targets.append(.target(name: name, dependencies: dependencies(for: name)))
+ pkg.products.append(.library(name: name, targets: [name]))
+
+ if let testTarget = has(tests: name) {
+ pkg.targets.append(testTarget)
+ }
+}
+
+pkg.targets += [
+ .testTarget(name: "Core", dependencies: ["PromiseKit"]),
+ .testTarget(name: "Cancel", dependencies: ["PromiseKit"]),
+ .testTarget(name: "APlusSwiftTests", dependencies: ["PromiseKit"], path: "Tests/A+/Swift"),
+ .testTarget(name: "APlusJSTests", dependencies: ["PromiseKit"], path: "Tests/A+/JavaScript", exclude: [
+ "index.js", "package-lock.json", "package.json", "README.md", "webpack.config.js", "build", "node_modules"
+ ]),
]
diff --git a/Package@swift-4.2.swift b/Package@swift-4.2.swift
deleted file mode 100644
index 571ea6b28..000000000
--- a/Package@swift-4.2.swift
+++ /dev/null
@@ -1,30 +0,0 @@
-// swift-tools-version:4.2
-
-import PackageDescription
-
-let pkg = Package(name: "PromiseKit")
-pkg.products = [
- .library(name: "PromiseKit", targets: ["PromiseKit"]),
-]
-
-let pmk: Target = .target(name: "PromiseKit")
-pmk.path = "Sources"
-pmk.exclude = [
- "AnyPromise.swift",
- "AnyPromise.m",
- "PMKCallVariadicBlock.m",
- "dispatch_promise.m",
- "join.m",
- "when.m",
- "NSMethodSignatureForBlock.m",
- "after.m",
- "hang.m",
- "race.m",
- "Deprecations.swift"
-]
-pkg.swiftLanguageVersions = [.v3, .v4, .v4_2]
-pkg.targets = [
- pmk,
- .testTarget(name: "APlus", dependencies: ["PromiseKit"], path: "Tests/A+"),
- .testTarget(name: "CorePromise", dependencies: ["PromiseKit"], path: "Tests/CorePromise"),
-]
diff --git a/Package@swift-5.0.swift b/Package@swift-5.0.swift
deleted file mode 100644
index 5d1ea438f..000000000
--- a/Package@swift-5.0.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-// swift-tools-version:5.0
-
-import PackageDescription
-
-let pkg = Package(name: "PromiseKit")
-pkg.platforms = [
- .macOS(.v10_10), .iOS(.v8), .tvOS(.v9), .watchOS(.v2)
-]
-pkg.products = [
- .library(name: "PromiseKit", targets: ["PromiseKit"]),
-]
-
-let pmk: Target = .target(name: "PromiseKit")
-pmk.path = "Sources"
-pmk.exclude = [
- "AnyPromise.swift",
- "AnyPromise.m",
- "PMKCallVariadicBlock.m",
- "dispatch_promise.m",
- "join.m",
- "when.m",
- "NSMethodSignatureForBlock.m",
- "after.m",
- "hang.m",
- "race.m",
- "Deprecations.swift"
-]
-pkg.swiftLanguageVersions = [.v4, .v4_2, .v5]
-pkg.targets = [
- pmk,
- .testTarget(name: "APlus", dependencies: ["PromiseKit"], path: "Tests/A+"),
- .testTarget(name: "CorePromise", dependencies: ["PromiseKit"], path: "Tests/CorePromise"),
-]
diff --git a/Package@swift-5.3.swift b/Package@swift-5.3.swift
deleted file mode 100644
index 0c4bf4d24..000000000
--- a/Package@swift-5.3.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-// swift-tools-version:5.3
-
-import PackageDescription
-
-let pkg = Package(name: "PromiseKit")
-pkg.platforms = [
- .macOS(.v10_10), .iOS(.v9), .tvOS(.v9), .watchOS(.v2)
-]
-pkg.products = [
- .library(name: "PromiseKit", targets: ["PromiseKit"]),
-]
-
-let pmk: Target = .target(name: "PromiseKit")
-pmk.path = "Sources"
-pmk.exclude = [
- "AnyPromise.swift",
- "AnyPromise.m",
- "PMKCallVariadicBlock.m",
- "dispatch_promise.m",
- "join.m",
- "when.m",
- "NSMethodSignatureForBlock.m",
- "after.m",
- "hang.m",
- "race.m",
- "Deprecations.swift",
- "Info.plist"
-]
-pkg.swiftLanguageVersions = [.v4, .v4_2, .v5]
-pkg.targets = [
- pmk,
- .testTarget(name: "APlus", dependencies: ["PromiseKit"], path: "Tests/A+", exclude: ["README.md"]),
- .testTarget(name: "CorePromise", dependencies: ["PromiseKit"], path: "Tests/CorePromise"),
-]
diff --git a/PromiseKit.playground/Contents.swift b/PromiseKit.playground/Contents.swift
deleted file mode 100644
index 3ade47e96..000000000
--- a/PromiseKit.playground/Contents.swift
+++ /dev/null
@@ -1,27 +0,0 @@
-import PlaygroundSupport
-
-// Is this erroring? If so open the `.xcodeproj` and build the
-// framework for a macOS target (usually labeled: “My Mac”).
-// Then select `PromiseKit.playground` from inside Xcode.
-import PromiseKit
-
-
-func promise3() -> Promise {
- return after(.seconds(1)).map{ 3 }
-}
-
-firstly {
- Promise.value(1)
-}.map { _ in
- 2
-}.then { _ in
- promise3()
-}.done {
- print($0) // => 3
-}.catch { error in
- // only happens for errors
-}.finally {
- PlaygroundPage.current.finishExecution()
-}
-
-PlaygroundPage.current.needsIndefiniteExecution = true
diff --git a/PromiseKit.playground/contents.xcplayground b/PromiseKit.playground/contents.xcplayground
deleted file mode 100644
index e6f503930..000000000
--- a/PromiseKit.playground/contents.xcplayground
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/PromiseKit.playground/playground.xcworkspace/contents.xcworkspacedata b/PromiseKit.playground/playground.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 919434a62..000000000
--- a/PromiseKit.playground/playground.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/PromiseKit.podspec b/PromiseKit.podspec
index 7873a82c7..544dc0412 100644
--- a/PromiseKit.podspec
+++ b/PromiseKit.podspec
@@ -1,12 +1,15 @@
Pod::Spec.new do |s|
s.name = "PromiseKit"
- s.version = '6.15.3'
+ s.version = ENV['PMKVersion'] || '7.999.0'
s.source = {
:git => "https://github.com/mxcl/#{s.name}.git",
- :tag => s.version,
- :submodules => true
+ :tag => s.version
+ }
+
+ s.pod_target_xcconfig = {
+ 'OTHER_SWIFT_FLAGS' => '-DPMKCocoaPods',
}
s.license = 'MIT'
@@ -15,75 +18,19 @@ Pod::Spec.new do |s|
s.description = 'A thoughtful and complete implementation of promises for iOS, macOS, watchOS and tvOS with first-class support for both Objective-C and Swift.'
s.social_media_url = 'https://twitter.com/mxcl'
s.authors = { 'Max Howell' => 'mxcl@me.com' }
- s.documentation_url = 'http://mxcl.dev/PromiseKit/reference/v6/Classes/Promise.html'
- s.default_subspecs = 'CorePromise', 'UIKit', 'Foundation'
+ s.documentation_url = 'http://mxcl.dev/PromiseKit/reference/v7/Classes/Promise.html'
+ s.default_subspecs = 'CorePromise', 'Foundation'
s.requires_arc = true
- s.swift_versions = ['3.2', '3.3', '3.4', '4.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '5.2', '5.3', '5.4']
+ s.swift_versions = ['5.3', '5.4']
- # CocoaPods requires us to specify the root deployment targets
- # even though for us it is nonsense. Our root spec has no
- # sources.
- s.ios.deployment_target = '8.0'
+ s.ios.deployment_target = '9.0'
s.osx.deployment_target = '10.10'
- s.watchos.deployment_target = '2.0'
+ s.watchos.deployment_target = '3.0'
s.tvos.deployment_target = '9.0'
- s.pod_target_xcconfig = {
- 'OTHER_SWIFT_FLAGS' => '-DPMKCocoaPods',
- }
-
- s.subspec 'Accounts' do |ss|
- ss.ios.source_files = ss.osx.source_files = 'Extensions/Accounts/Sources/*'
- ss.ios.frameworks = ss.osx.frameworks = 'Accounts'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- end
-
- s.subspec 'Alamofire' do |ss|
- ss.source_files = 'Extensions/Alamofire/Sources/*'
- ss.dependency 'Alamofire', '~> 4.0'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.11'
- ss.watchos.deployment_target = '2.0'
- ss.tvos.deployment_target = '9.0'
- end
-
- s.subspec 'AddressBook' do |ss|
- ss.ios.source_files = 'Extensions/AddressBook/Sources/*'
- ss.ios.frameworks = 'AddressBook'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- end
-
- s.subspec 'AssetsLibrary' do |ss|
- ss.ios.source_files = 'Extensions/AssetsLibrary/Sources/*'
- ss.ios.frameworks = 'AssetsLibrary'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- end
-
- s.subspec 'AVFoundation' do |ss|
- ss.ios.source_files = 'Extensions/AVFoundation/Sources/*'
- ss.ios.frameworks = 'AVFoundation'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- end
-
- s.subspec 'Bolts' do |ss|
- ss.source_files = 'Extensions/Bolts/Sources/*'
- ss.dependency 'PromiseKit/CorePromise'
- ss.dependency 'Bolts', '~> 1.9.0'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.watchos.deployment_target = '2.0'
- ss.tvos.deployment_target = '9.0'
- end
-
s.subspec 'CloudKit' do |ss|
- ss.source_files = 'Extensions/CloudKit/Sources/*'
+ ss.source_files = 'Sources/PMKCloudKit/*'
ss.frameworks = 'CloudKit'
ss.dependency 'PromiseKit/CorePromise'
ss.ios.deployment_target = '10.0'
@@ -92,27 +39,9 @@ Pod::Spec.new do |s|
ss.watchos.deployment_target = '3.0'
end
- s.subspec 'CoreBluetooth' do |ss|
- ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Extensions/CoreBluetooth/Sources/*'
- ss.ios.frameworks = ss.osx.frameworks = ss.tvos.frameworks = 'CoreBluetooth'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.tvos.deployment_target = '9.0'
- end
-
s.subspec 'CorePromise' do |ss|
- hh = Dir['Sources/*.h'] - Dir['Sources/*+Private.h']
-
- cc = Dir['Sources/*.swift'] - ['Sources/SwiftPM.swift']
- cc << 'Sources/{after,AnyPromise,GlobalState,dispatch_promise,hang,join,PMKPromise,when,race}.m'
- cc += hh
-
- ss.source_files = cc
- ss.public_header_files = hh
- ss.preserve_paths = 'Sources/AnyPromise+Private.h', 'Sources/PMKCallVariadicBlock.m', 'Sources/NSMethodSignatureForBlock.m'
+ ss.source_files = 'Sources/PromiseKit/**/*'
ss.frameworks = 'Foundation'
-
ss.ios.deployment_target = '8.0'
ss.osx.deployment_target = '10.10'
ss.watchos.deployment_target = '2.0'
@@ -120,8 +49,7 @@ Pod::Spec.new do |s|
end
s.subspec 'CoreLocation' do |ss|
- ss.source_files = 'Extensions/CoreLocation/Sources/*'
- ss.watchos.source_files = 'Extensions/CoreLocation/Sources/CLGeocoder*'
+ ss.source_files = 'Sources/PMKCoreLocation/*'
ss.dependency 'PromiseKit/CorePromise'
ss.frameworks = 'CoreLocation'
@@ -131,18 +59,8 @@ Pod::Spec.new do |s|
ss.tvos.deployment_target = '9.0'
end
- s.subspec 'EventKit' do |ss|
- ss.ios.source_files = ss.osx.source_files = ss.watchos.source_files = 'Extensions/EventKit/Sources/*'
- ss.ios.frameworks = ss.osx.frameworks = ss.watchos.frameworks = 'EventKit'
- ss.dependency 'PromiseKit/CorePromise'
-
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.watchos.deployment_target = '2.0'
- end
-
s.subspec 'Foundation' do |ss|
- ss.source_files = Dir['Extensions/Foundation/Sources/*']
+ ss.source_files = 'Sources/PMKFoundation/*'
ss.dependency 'PromiseKit/CorePromise'
ss.frameworks = 'Foundation'
ss.ios.deployment_target = '8.0'
@@ -152,7 +70,7 @@ Pod::Spec.new do |s|
end
s.subspec 'HealthKit' do |ss|
- ss.source_files = Dir['Extensions/HealthKit/Sources/*']
+ ss.source_files = 'Sources/PMKHealthKit/*'
ss.dependency 'PromiseKit/CorePromise'
ss.frameworks = 'HealthKit'
ss.ios.deployment_target = '9.0'
@@ -160,7 +78,7 @@ Pod::Spec.new do |s|
end
s.subspec 'HomeKit' do |ss|
- ss.source_files = Dir['Extensions/HomeKit/Sources/*']
+ ss.source_files = 'Sources/PMKHomeKit/*'
ss.dependency 'PromiseKit/CorePromise'
ss.frameworks = 'HomeKit'
ss.ios.deployment_target = '8.0'
@@ -169,7 +87,7 @@ Pod::Spec.new do |s|
end
s.subspec 'MapKit' do |ss|
- ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Extensions/MapKit/Sources/*'
+ ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Sources/PMKMapKit/*'
ss.ios.frameworks = ss.osx.frameworks = ss.tvos.frameworks = 'MapKit'
ss.dependency 'PromiseKit/CorePromise'
ss.ios.deployment_target = '8.0'
@@ -178,100 +96,21 @@ Pod::Spec.new do |s|
ss.tvos.deployment_target = '9.2'
end
- s.subspec 'MessageUI' do |ss|
- ss.ios.source_files = 'Extensions/MessagesUI/Sources/*'
- ss.ios.frameworks = 'MessageUI'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- end
-
- s.subspec 'OMGHTTPURLRQ' do |ss|
- ss.source_files = 'Extensions/OMGHTTPURLRQ/Sources/*'
- ss.dependency 'PromiseKit/Foundation'
- ss.dependency 'OMGHTTPURLRQ', '~> 3.2'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.watchos.deployment_target = '2.0'
- ss.tvos.deployment_target = '9.0'
- end
-
s.subspec 'Photos' do |ss|
- ss.ios.source_files = ss.tvos.source_files = ss.osx.source_files = 'Extensions/Photos/Sources/*'
+ ss.ios.source_files = ss.tvos.source_files = ss.osx.source_files = 'Sources/PMKPhotos/*'
ss.ios.frameworks = ss.tvos.frameworks = ss.osx.frameworks = 'Photos'
ss.dependency 'PromiseKit/CorePromise'
-
ss.ios.deployment_target = '8.0'
ss.osx.deployment_target = '10.13'
ss.tvos.deployment_target = '10.0'
end
- s.subspec 'QuartzCore' do |ss|
- ss.osx.source_files = ss.ios.source_files = ss.tvos.source_files = 'Extensions/QuartzCore/Sources/*'
- ss.osx.frameworks = ss.ios.frameworks = ss.tvos.frameworks = 'QuartzCore'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.tvos.deployment_target = '9.0'
- end
-
- s.subspec 'Social' do |ss|
- ss.ios.source_files = 'Extensions/Social/Sources/*'
- ss.osx.source_files = Dir['Extensions/Social/Sources/*'] - ['Categories/Social/Sources/*SLComposeViewController+Promise.swift']
- ss.ios.frameworks = ss.osx.frameworks = 'Social'
- ss.dependency 'PromiseKit/Foundation'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- end
-
s.subspec 'StoreKit' do |ss|
- ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Extensions/StoreKit/Sources/*'
+ ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Sources/PMKStoreKit/*'
ss.ios.frameworks = ss.osx.frameworks = ss.tvos.frameworks = 'StoreKit'
ss.dependency 'PromiseKit/CorePromise'
ss.ios.deployment_target = '8.0'
ss.osx.deployment_target = '10.10'
ss.tvos.deployment_target = '9.0'
end
-
- s.subspec 'SystemConfiguration' do |ss|
- ss.ios.source_files = ss.osx.source_files = ss.tvos.source_files = 'Extensions/SystemConfiguration/Sources/*'
- ss.ios.frameworks = ss.osx.frameworks = ss.tvos.frameworks = 'SystemConfiguration'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.osx.deployment_target = '10.10'
- ss.tvos.deployment_target = '9.0'
- end
-
- picker_cc = 'Extensions/UIKit/Sources/UIImagePickerController+Promise.swift'
-
- s.subspec 'UIKit' do |ss|
- ss.ios.source_files = ss.tvos.source_files = Dir['Extensions/UIKit/Sources/*'] - [picker_cc]
- ss.tvos.frameworks = ss.ios.frameworks = 'UIKit'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.tvos.deployment_target = '9.0'
- end
-
- s.subspec 'UIImagePickerController' do |ss|
- # Since iOS 10, App Store submissions that contain references to
- # UIImagePickerController (even if unused in 3rd party libraries)
- # are rejected unless an Info.plist key is specified, thus we
- # moved this code to a sub-subspec.
- #
- # This *was* a subspec of UIKit, but bizarrely CocoaPods would
- # include this when specifying *just* UIKit…!
-
- ss.ios.source_files = picker_cc
- ss.ios.frameworks = 'UIKit'
- ss.ios.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) PMKImagePickerController=1' }
- ss.dependency 'PromiseKit/UIKit'
- ss.ios.deployment_target = '8.0'
- end
-
- s.subspec 'WatchConnectivity' do |ss|
- ss.ios.source_files = ss.watchos.source_files = 'Extensions/WatchConnectivity/Sources/*'
- ss.ios.frameworks = ss.watchos.frameworks = 'WatchConnectivity'
- ss.dependency 'PromiseKit/CorePromise'
- ss.ios.deployment_target = '8.0'
- ss.watchos.deployment_target = '2.0'
- end
end
diff --git a/PromiseKit.xcodeproj/project.pbxproj b/PromiseKit.xcodeproj/project.pbxproj
deleted file mode 100644
index eeeecf1d4..000000000
--- a/PromiseKit.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,1230 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- 085B96B321A6359500E5E22F /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085B96B121A6358900E5E22F /* LoggingTests.swift */; };
- 085B96BF21A9B37C00E5E22F /* LogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085B96BE21A9B37C00E5E22F /* LogEvent.swift */; };
- 0C42F31B1FCF86320051309C /* HangTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C42F3191FCF86240051309C /* HangTests.swift */; };
- 0CC3AF2B1FCF84F7000E98C9 /* hang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CC3AF2A1FCF84F7000E98C9 /* hang.swift */; };
- 49A5584D1DC5185900E4D01B /* ResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A5584B1DC5172F00E4D01B /* ResolverTests.swift */; };
- 630A8056203CEF6800D25F23 /* AnyPromiseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 630A8051203CEF6800D25F23 /* AnyPromiseTests.m */; settings = {COMPILER_FLAGS = "-fobjc-arc-exceptions"; }; };
- 630A8057203CEF6800D25F23 /* PMKManifoldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 630A8052203CEF6800D25F23 /* PMKManifoldTests.m */; };
- 630A8058203CEF6800D25F23 /* JoinTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 630A8053203CEF6800D25F23 /* JoinTests.m */; };
- 630A8059203CEF6800D25F23 /* HangTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 630A8054203CEF6800D25F23 /* HangTests.m */; };
- 630A805A203CEF6800D25F23 /* WhenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 630A8055203CEF6800D25F23 /* WhenTests.m */; };
- 630A805B203CF67800D25F23 /* DefaultDispatchQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D641B1D59635300BC0AF5 /* DefaultDispatchQueueTests.swift */; };
- 631411381D59795700E24B9E /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
- 631411431D59797100E24B9E /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6314113E1D59797100E24B9E /* BridgingTests.m */; };
- 631411441D59797100E24B9E /* BridgingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6314113F1D59797100E24B9E /* BridgingTests.swift */; };
- 631411451D59797100E24B9E /* Infrastructure.m in Sources */ = {isa = PBXBuildFile; fileRef = 631411411D59797100E24B9E /* Infrastructure.m */; };
- 631411461D59797100E24B9E /* Infrastructure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631411421D59797100E24B9E /* Infrastructure.swift */; };
- 631751A41D59766500A9DDDC /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
- 631751B71D59768200A9DDDC /* 0.0.0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751AB1D59768200A9DDDC /* 0.0.0.swift */; };
- 631751B81D59768200A9DDDC /* 2.1.2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751AC1D59768200A9DDDC /* 2.1.2.swift */; };
- 631751B91D59768200A9DDDC /* 2.1.3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751AD1D59768200A9DDDC /* 2.1.3.swift */; };
- 631751BA1D59768200A9DDDC /* 2.2.2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751AE1D59768200A9DDDC /* 2.2.2.swift */; };
- 631751BB1D59768200A9DDDC /* 2.2.3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751AF1D59768200A9DDDC /* 2.2.3.swift */; };
- 631751BC1D59768200A9DDDC /* 2.2.4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B01D59768200A9DDDC /* 2.2.4.swift */; };
- 631751BD1D59768200A9DDDC /* 2.2.6.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B11D59768200A9DDDC /* 2.2.6.swift */; };
- 631751BE1D59768200A9DDDC /* 2.2.7.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B21D59768200A9DDDC /* 2.2.7.swift */; };
- 631751BF1D59768200A9DDDC /* 2.3.1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B31D59768200A9DDDC /* 2.3.1.swift */; };
- 631751C01D59768200A9DDDC /* 2.3.2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B41D59768200A9DDDC /* 2.3.2.swift */; };
- 631751C11D59768200A9DDDC /* 2.3.4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 631751B51D59768200A9DDDC /* 2.3.4.swift */; };
- 632FBBE31F33B273008F8FBB /* Catchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 632FBBE21F33B273008F8FBB /* Catchable.swift */; };
- 632FBBE51F33B338008F8FBB /* CatchableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 632FBBE41F33B338008F8FBB /* CatchableTests.swift */; };
- 633027E6203CC0060037E136 /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
- 6330B5E11F2E991200D60528 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6330B5E01F2E991200D60528 /* Configuration.swift */; };
- 634AAD2B1EAE517C00B17855 /* fwd.h in Headers */ = {isa = PBXBuildFile; fileRef = 634AAD2A1EAE517C00B17855 /* fwd.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 635D641D1D59635300BC0AF5 /* PromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64081D59635300BC0AF5 /* PromiseTests.swift */; };
- 635D641E1D59635300BC0AF5 /* CancellableErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64091D59635300BC0AF5 /* CancellableErrorTests.swift */; };
- 635D64221D59635300BC0AF5 /* ZalgoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D640D1D59635300BC0AF5 /* ZalgoTests.swift */; };
- 635D64231D59635300BC0AF5 /* AfterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D640E1D59635300BC0AF5 /* AfterTests.swift */; };
- 635D64261D59635300BC0AF5 /* WhenResolvedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64111D59635300BC0AF5 /* WhenResolvedTests.swift */; };
- 635D64271D59635300BC0AF5 /* RaceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64121D59635300BC0AF5 /* RaceTests.swift */; };
- 635D64281D59635300BC0AF5 /* WhenConcurrentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64131D59635300BC0AF5 /* WhenConcurrentTests.swift */; };
- 635D642A1D59635300BC0AF5 /* WhenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64151D59635300BC0AF5 /* WhenTests.swift */; };
- 635D642B1D59635300BC0AF5 /* StressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64161D59635300BC0AF5 /* StressTests.swift */; };
- 635D642C1D59635300BC0AF5 /* RegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 635D64171D59635300BC0AF5 /* RegressionTests.swift */; };
- 635D64301D596E8500BC0AF5 /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
- 636A291A1F1C156B001229C2 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A29191F1C156B001229C2 /* Promise.swift */; };
- 636A291F1F1C16FF001229C2 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A291E1F1C16FF001229C2 /* Box.swift */; };
- 636A29211F1C1716001229C2 /* Thenable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A29201F1C1716001229C2 /* Thenable.swift */; };
- 636A29231F1C17A6001229C2 /* Guarantee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A29221F1C17A6001229C2 /* Guarantee.swift */; };
- 636A29251F1C3089001229C2 /* race.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A29241F1C3089001229C2 /* race.swift */; };
- 636A29271F1C3927001229C2 /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636A29261F1C3927001229C2 /* Resolver.swift */; };
- 639BF757203DF03100FA577B /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639BF755203DF02C00FA577B /* Utilities.swift */; };
- 63B0AC7F1D595E6300FA21D9 /* after.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC611D595E6300FA21D9 /* after.m */; };
- 63B0AC801D595E6300FA21D9 /* after.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC621D595E6300FA21D9 /* after.swift */; };
- 63B0AC811D595E6300FA21D9 /* AnyPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 63B0AC631D595E6300FA21D9 /* AnyPromise.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 63B0AC821D595E6300FA21D9 /* AnyPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC641D595E6300FA21D9 /* AnyPromise.m */; };
- 63B0AC831D595E6300FA21D9 /* AnyPromise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC651D595E6300FA21D9 /* AnyPromise.swift */; };
- 63B0AC841D595E6300FA21D9 /* AnyPromise+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 63B0AC661D595E6300FA21D9 /* AnyPromise+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 63B0AC851D595E6300FA21D9 /* dispatch_promise.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC671D595E6300FA21D9 /* dispatch_promise.m */; };
- 63B0AC871D595E6300FA21D9 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC691D595E6300FA21D9 /* Error.swift */; };
- 63B0AC891D595E6300FA21D9 /* hang.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC6B1D595E6300FA21D9 /* hang.m */; };
- 63B0AC8B1D595E6300FA21D9 /* join.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC6D1D595E6300FA21D9 /* join.m */; };
- 63B0AC931D595E6300FA21D9 /* PromiseKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 63B0AC761D595E6300FA21D9 /* PromiseKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 63B0AC991D595E6300FA21D9 /* when.m in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC7C1D595E6300FA21D9 /* when.m */; };
- 63B0AC9A1D595E6300FA21D9 /* when.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B0AC7D1D595E6300FA21D9 /* when.swift */; };
- 63B18AEC1F2D205C00B79E37 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B18AEB1F2D205C00B79E37 /* CustomStringConvertible.swift */; };
- 63B7C94B203E2B8200FBEC00 /* AnyPromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B7C94A203E2B8200FBEC00 /* AnyPromiseTests.swift */; };
- 63B912AA1F1D7B1300D49110 /* firstly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B912A91F1D7B1300D49110 /* firstly.swift */; };
- 63CF6D7A203CC66000EC8927 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CF6D79203CC66000EC8927 /* ErrorTests.swift */; };
- 63CF6D7C203CCDAB00EC8927 /* GuaranteeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CF6D7B203CCDAB00EC8927 /* GuaranteeTests.swift */; };
- 63CF6D7E203CD12700EC8927 /* DeprecationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63648C94203CB97400EBA011 /* DeprecationTests.swift */; };
- 63CF6D80203CD19200EC8927 /* ThenableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CF6D7F203CD19200EC8927 /* ThenableTests.swift */; };
- 63D9B2EF203385FD0075C00B /* race.m in Sources */ = {isa = PBXBuildFile; fileRef = 63D9B2EE203385FD0075C00B /* race.m */; };
- 63D9B2F120338D5D0075C00B /* Deprecations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D9B2F020338D5D0075C00B /* Deprecations.swift */; };
- C013F7382048E3B6006B57B1 /* MockNodeEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F7372048E3B6006B57B1 /* MockNodeEnvironment.swift */; };
- C013F73A2049076A006B57B1 /* JSPromise.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F7392049076A006B57B1 /* JSPromise.swift */; };
- C013F73C20494291006B57B1 /* JSAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F73B20494291006B57B1 /* JSAdapter.swift */; };
- C013F740204E5064006B57B1 /* JSUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F73F204E5063006B57B1 /* JSUtils.swift */; };
- C0244E5E2047A6CB00ACB4AC /* PromiseKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */; };
- C0244E692047AC9F00ACB4AC /* AllTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0244E682047AC9F00ACB4AC /* AllTests.swift */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXContainerItemProxy section */
- 631411341D59795700E24B9E /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 6399A3721D595D9100D65233 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 63B0AC561D595E1B00FA21D9;
- remoteInfo = PromiseKit;
- };
- 6317518D1D59766500A9DDDC /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 6399A3721D595D9100D65233 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 63B0AC561D595E1B00FA21D9;
- remoteInfo = PromiseKit;
- };
- 633027E2203CC0060037E136 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 6399A3721D595D9100D65233 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 63B0AC561D595E1B00FA21D9;
- remoteInfo = PromiseKit;
- };
- 635D64041D5962F900BC0AF5 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 6399A3721D595D9100D65233 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 63B0AC561D595E1B00FA21D9;
- remoteInfo = PromiseKit;
- };
- C0244E502047A6CB00ACB4AC /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 6399A3721D595D9100D65233 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 63B0AC561D595E1B00FA21D9;
- remoteInfo = PromiseKit;
- };
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- C0244E6E2047AF0B00ACB4AC /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 7;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 085B96B121A6358900E5E22F /* LoggingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingTests.swift; sourceTree = ""; };
- 085B96BE21A9B37C00E5E22F /* LogEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LogEvent.swift; path = Sources/LogEvent.swift; sourceTree = ""; };
- 0C42F3191FCF86240051309C /* HangTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HangTests.swift; sourceTree = ""; };
- 0CC3AF2A1FCF84F7000E98C9 /* hang.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = hang.swift; path = Sources/hang.swift; sourceTree = ""; };
- 49A5584B1DC5172F00E4D01B /* ResolverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResolverTests.swift; sourceTree = ""; };
- 630019221D596292003B4E30 /* PMKCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 630A8051203CEF6800D25F23 /* AnyPromiseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnyPromiseTests.m; sourceTree = ""; };
- 630A8052203CEF6800D25F23 /* PMKManifoldTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PMKManifoldTests.m; sourceTree = ""; };
- 630A8053203CEF6800D25F23 /* JoinTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JoinTests.m; sourceTree = ""; };
- 630A8054203CEF6800D25F23 /* HangTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HangTests.m; sourceTree = ""; };
- 630A8055203CEF6800D25F23 /* WhenTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WhenTests.m; sourceTree = ""; };
- 6314113C1D59795700E24B9E /* PMKBridgeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKBridgeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 6314113E1D59797100E24B9E /* BridgingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BridgingTests.m; sourceTree = ""; };
- 6314113F1D59797100E24B9E /* BridgingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgingTests.swift; sourceTree = ""; };
- 631411401D59797100E24B9E /* Infrastructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Infrastructure.h; sourceTree = ""; };
- 631411411D59797100E24B9E /* Infrastructure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Infrastructure.m; sourceTree = ""; };
- 631411421D59797100E24B9E /* Infrastructure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Infrastructure.swift; sourceTree = ""; };
- 631751A81D59766500A9DDDC /* PMKA+Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PMKA+Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- 631751AB1D59768200A9DDDC /* 0.0.0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 0.0.0.swift; sourceTree = ""; };
- 631751AC1D59768200A9DDDC /* 2.1.2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.1.2.swift; sourceTree = ""; };
- 631751AD1D59768200A9DDDC /* 2.1.3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.1.3.swift; sourceTree = ""; };
- 631751AE1D59768200A9DDDC /* 2.2.2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.2.2.swift; sourceTree = ""; };
- 631751AF1D59768200A9DDDC /* 2.2.3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.2.3.swift; sourceTree = ""; };
- 631751B01D59768200A9DDDC /* 2.2.4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.2.4.swift; sourceTree = ""; };
- 631751B11D59768200A9DDDC /* 2.2.6.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.2.6.swift; sourceTree = ""; };
- 631751B21D59768200A9DDDC /* 2.2.7.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.2.7.swift; sourceTree = ""; };
- 631751B31D59768200A9DDDC /* 2.3.1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.3.1.swift; sourceTree = ""; };
- 631751B41D59768200A9DDDC /* 2.3.2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.3.2.swift; sourceTree = ""; };
- 631751B51D59768200A9DDDC /* 2.3.4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 2.3.4.swift; sourceTree = ""; };
- 631751B61D59768200A9DDDC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
- 632FBBE21F33B273008F8FBB /* Catchable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Catchable.swift; path = Sources/Catchable.swift; sourceTree = ""; };
- 632FBBE41F33B338008F8FBB /* CatchableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CatchableTests.swift; sourceTree = ""; };
- 633027EA203CC0060037E136 /* PMKDeprecatedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKDeprecatedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 6330B5E01F2E991200D60528 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Sources/Configuration.swift; sourceTree = ""; };
- 634AAD2A1EAE517C00B17855 /* fwd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fwd.h; path = Sources/fwd.h; sourceTree = ""; };
- 635893921D5BE4E000F14B55 /* PromiseKit.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = PromiseKit.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
- 635893941D5BE4F900F14B55 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; };
- 635893951D5BE4F900F14B55 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; };
- 635893961D5BE4F900F14B55 /* PromiseKit.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; name = PromiseKit.podspec; path = .github/PromiseKit.podspec; sourceTree = ""; };
- 635893971D5BE4F900F14B55 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
- 635D64081D59635300BC0AF5 /* PromiseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseTests.swift; sourceTree = ""; };
- 635D64091D59635300BC0AF5 /* CancellableErrorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CancellableErrorTests.swift; sourceTree = ""; };
- 635D640D1D59635300BC0AF5 /* ZalgoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZalgoTests.swift; sourceTree = ""; };
- 635D640E1D59635300BC0AF5 /* AfterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AfterTests.swift; sourceTree = ""; };
- 635D64111D59635300BC0AF5 /* WhenResolvedTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhenResolvedTests.swift; sourceTree = ""; };
- 635D64121D59635300BC0AF5 /* RaceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaceTests.swift; sourceTree = ""; };
- 635D64131D59635300BC0AF5 /* WhenConcurrentTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhenConcurrentTests.swift; sourceTree = ""; };
- 635D64151D59635300BC0AF5 /* WhenTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhenTests.swift; sourceTree = ""; };
- 635D64161D59635300BC0AF5 /* StressTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StressTests.swift; sourceTree = ""; };
- 635D64171D59635300BC0AF5 /* RegressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegressionTests.swift; sourceTree = ""; };
- 635D641B1D59635300BC0AF5 /* DefaultDispatchQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultDispatchQueueTests.swift; sourceTree = ""; };
- 63648C94203CB97400EBA011 /* DeprecationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeprecationTests.swift; path = Tests/DeprecationTests.swift; sourceTree = ""; };
- 636A29191F1C156B001229C2 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Promise.swift; path = Sources/Promise.swift; sourceTree = ""; };
- 636A291E1F1C16FF001229C2 /* Box.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Box.swift; path = Sources/Box.swift; sourceTree = ""; };
- 636A29201F1C1716001229C2 /* Thenable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Thenable.swift; path = Sources/Thenable.swift; sourceTree = ""; };
- 636A29221F1C17A6001229C2 /* Guarantee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Guarantee.swift; path = Sources/Guarantee.swift; sourceTree = ""; };
- 636A29241F1C3089001229C2 /* race.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = race.swift; path = Sources/race.swift; sourceTree = ""; };
- 636A29261F1C3927001229C2 /* Resolver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Resolver.swift; path = Sources/Resolver.swift; sourceTree = ""; };
- 639BF755203DF02C00FA577B /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; };
- 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PromiseKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- 63B0AC611D595E6300FA21D9 /* after.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = after.m; path = Sources/after.m; sourceTree = ""; };
- 63B0AC621D595E6300FA21D9 /* after.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = after.swift; path = Sources/after.swift; sourceTree = ""; };
- 63B0AC631D595E6300FA21D9 /* AnyPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnyPromise.h; path = Sources/AnyPromise.h; sourceTree = ""; };
- 63B0AC641D595E6300FA21D9 /* AnyPromise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AnyPromise.m; path = Sources/AnyPromise.m; sourceTree = ""; };
- 63B0AC651D595E6300FA21D9 /* AnyPromise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnyPromise.swift; path = Sources/AnyPromise.swift; sourceTree = ""; };
- 63B0AC661D595E6300FA21D9 /* AnyPromise+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "AnyPromise+Private.h"; path = "Sources/AnyPromise+Private.h"; sourceTree = ""; };
- 63B0AC671D595E6300FA21D9 /* dispatch_promise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = dispatch_promise.m; path = Sources/dispatch_promise.m; sourceTree = ""; };
- 63B0AC691D595E6300FA21D9 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Error.swift; path = Sources/Error.swift; sourceTree = ""; };
- 63B0AC6B1D595E6300FA21D9 /* hang.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = hang.m; path = Sources/hang.m; sourceTree = ""; };
- 63B0AC6C1D595E6300FA21D9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Sources/Info.plist; sourceTree = ""; };
- 63B0AC6D1D595E6300FA21D9 /* join.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = join.m; path = Sources/join.m; sourceTree = ""; };
- 63B0AC6F1D595E6300FA21D9 /* NSMethodSignatureForBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSMethodSignatureForBlock.m; path = Sources/NSMethodSignatureForBlock.m; sourceTree = ""; };
- 63B0AC711D595E6300FA21D9 /* PMKCallVariadicBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PMKCallVariadicBlock.m; path = Sources/PMKCallVariadicBlock.m; sourceTree = ""; };
- 63B0AC761D595E6300FA21D9 /* PromiseKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PromiseKit.h; path = Sources/PromiseKit.h; sourceTree = ""; };
- 63B0AC7C1D595E6300FA21D9 /* when.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = when.m; path = Sources/when.m; sourceTree = ""; };
- 63B0AC7D1D595E6300FA21D9 /* when.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = when.swift; path = Sources/when.swift; sourceTree = ""; };
- 63B18AEB1F2D205C00B79E37 /* CustomStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CustomStringConvertible.swift; path = Sources/CustomStringConvertible.swift; sourceTree = ""; };
- 63B7C94A203E2B8200FBEC00 /* AnyPromiseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyPromiseTests.swift; sourceTree = ""; };
- 63B912A91F1D7B1300D49110 /* firstly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = firstly.swift; path = Sources/firstly.swift; sourceTree = ""; };
- 63CF6D79203CC66000EC8927 /* ErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTests.swift; sourceTree = ""; };
- 63CF6D7B203CCDAB00EC8927 /* GuaranteeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuaranteeTests.swift; sourceTree = ""; };
- 63CF6D7F203CD19200EC8927 /* ThenableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThenableTests.swift; sourceTree = ""; };
- 63D9B2EE203385FD0075C00B /* race.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = race.m; path = Sources/race.m; sourceTree = ""; };
- 63D9B2F020338D5D0075C00B /* Deprecations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Deprecations.swift; path = Sources/Deprecations.swift; sourceTree = ""; };
- C013F7372048E3B6006B57B1 /* MockNodeEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MockNodeEnvironment.swift; path = "Tests/JS-A+/MockNodeEnvironment.swift"; sourceTree = ""; };
- C013F7392049076A006B57B1 /* JSPromise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = JSPromise.swift; path = "Tests/JS-A+/JSPromise.swift"; sourceTree = ""; };
- C013F73B20494291006B57B1 /* JSAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = JSAdapter.swift; path = "Tests/JS-A+/JSAdapter.swift"; sourceTree = ""; };
- C013F73F204E5063006B57B1 /* JSUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSUtils.swift; path = "Tests/JS-A+/JSUtils.swift"; sourceTree = ""; };
- C0244E622047A6CB00ACB4AC /* PMKJSA+Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PMKJSA+Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- C0244E682047AC9F00ACB4AC /* AllTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AllTests.swift; path = "Tests/JS-A+/AllTests.swift"; sourceTree = ""; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 630019181D596292003B4E30 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 635D64301D596E8500BC0AF5 /* PromiseKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 631411371D59795700E24B9E /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 631411381D59795700E24B9E /* PromiseKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 631751A31D59766500A9DDDC /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 631751A41D59766500A9DDDC /* PromiseKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 633027E5203CC0060037E136 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 633027E6203CC0060037E136 /* PromiseKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 63B0AC531D595E1B00FA21D9 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- C0244E5D2047A6CB00ACB4AC /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- C0244E5E2047A6CB00ACB4AC /* PromiseKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 630A8050203CEF6800D25F23 /* CoreObjC */ = {
- isa = PBXGroup;
- children = (
- 630A8051203CEF6800D25F23 /* AnyPromiseTests.m */,
- 63B7C94A203E2B8200FBEC00 /* AnyPromiseTests.swift */,
- 630A8052203CEF6800D25F23 /* PMKManifoldTests.m */,
- 630A8053203CEF6800D25F23 /* JoinTests.m */,
- 630A8054203CEF6800D25F23 /* HangTests.m */,
- 630A8055203CEF6800D25F23 /* WhenTests.m */,
- );
- name = CoreObjC;
- path = Tests/CoreObjC;
- sourceTree = "";
- };
- 630B60BF1F2F739E00A1AEFE /* Features */ = {
- isa = PBXGroup;
- children = (
- 63B0AC611D595E6300FA21D9 /* after.m */,
- 63B0AC6B1D595E6300FA21D9 /* hang.m */,
- 63B0AC6D1D595E6300FA21D9 /* join.m */,
- 63B0AC7C1D595E6300FA21D9 /* when.m */,
- 63D9B2EE203385FD0075C00B /* race.m */,
- );
- name = Features;
- sourceTree = "";
- };
- 630B60C01F2F73B000A1AEFE /* Headers */ = {
- isa = PBXGroup;
- children = (
- 634AAD2A1EAE517C00B17855 /* fwd.h */,
- 63B0AC631D595E6300FA21D9 /* AnyPromise.h */,
- );
- name = Headers;
- sourceTree = "";
- };
- 6314113D1D59797100E24B9E /* Bridging */ = {
- isa = PBXGroup;
- children = (
- 6314113E1D59797100E24B9E /* BridgingTests.m */,
- 6314113F1D59797100E24B9E /* BridgingTests.swift */,
- 631411401D59797100E24B9E /* Infrastructure.h */,
- 631411411D59797100E24B9E /* Infrastructure.m */,
- 631411421D59797100E24B9E /* Infrastructure.swift */,
- );
- name = Bridging;
- path = Tests/Bridging;
- sourceTree = "";
- };
- 6317518A1D59765700A9DDDC /* Core */ = {
- isa = PBXGroup;
- children = (
- 63CF6D7F203CD19200EC8927 /* ThenableTests.swift */,
- 632FBBE41F33B338008F8FBB /* CatchableTests.swift */,
- 635D64081D59635300BC0AF5 /* PromiseTests.swift */,
- 49A5584B1DC5172F00E4D01B /* ResolverTests.swift */,
- 63CF6D7B203CCDAB00EC8927 /* GuaranteeTests.swift */,
- 635D64091D59635300BC0AF5 /* CancellableErrorTests.swift */,
- 63CF6D79203CC66000EC8927 /* ErrorTests.swift */,
- 635D64151D59635300BC0AF5 /* WhenTests.swift */,
- 635D64131D59635300BC0AF5 /* WhenConcurrentTests.swift */,
- 635D64111D59635300BC0AF5 /* WhenResolvedTests.swift */,
- 635D640E1D59635300BC0AF5 /* AfterTests.swift */,
- 0C42F3191FCF86240051309C /* HangTests.swift */,
- 635D64121D59635300BC0AF5 /* RaceTests.swift */,
- 635D641B1D59635300BC0AF5 /* DefaultDispatchQueueTests.swift */,
- 635D64171D59635300BC0AF5 /* RegressionTests.swift */,
- 635D64161D59635300BC0AF5 /* StressTests.swift */,
- 635D640D1D59635300BC0AF5 /* ZalgoTests.swift */,
- 639BF755203DF02C00FA577B /* Utilities.swift */,
- 085B96B121A6358900E5E22F /* LoggingTests.swift */,
- );
- name = Core;
- path = Tests/CorePromise;
- sourceTree = "";
- };
- 631751AA1D59768200A9DDDC /* A+ */ = {
- isa = PBXGroup;
- children = (
- 631751AB1D59768200A9DDDC /* 0.0.0.swift */,
- 631751AC1D59768200A9DDDC /* 2.1.2.swift */,
- 631751AD1D59768200A9DDDC /* 2.1.3.swift */,
- 631751AE1D59768200A9DDDC /* 2.2.2.swift */,
- 631751AF1D59768200A9DDDC /* 2.2.3.swift */,
- 631751B01D59768200A9DDDC /* 2.2.4.swift */,
- 631751B11D59768200A9DDDC /* 2.2.6.swift */,
- 631751B21D59768200A9DDDC /* 2.2.7.swift */,
- 631751B31D59768200A9DDDC /* 2.3.1.swift */,
- 631751B41D59768200A9DDDC /* 2.3.2.swift */,
- 631751B51D59768200A9DDDC /* 2.3.4.swift */,
- 631751B61D59768200A9DDDC /* README.md */,
- );
- name = "A+";
- path = "Tests/A+";
- sourceTree = "";
- };
- 635893991D5BE51700F14B55 /* … */ = {
- isa = PBXGroup;
- children = (
- 63B0AC581D595E1B00FA21D9 /* Products */,
- 63B0AC6C1D595E6300FA21D9 /* Info.plist */,
- 635893941D5BE4F900F14B55 /* LICENSE */,
- 635893951D5BE4F900F14B55 /* Package.swift */,
- 635893961D5BE4F900F14B55 /* PromiseKit.podspec */,
- );
- name = "…";
- sourceTree = "";
- };
- 635D64061D59630200BC0AF5 /* Tests */ = {
- isa = PBXGroup;
- children = (
- C0244E6B2047ACAF00ACB4AC /* JS/A+ */,
- 631751AA1D59768200A9DDDC /* A+ */,
- 6314113D1D59797100E24B9E /* Bridging */,
- 6317518A1D59765700A9DDDC /* Core */,
- 630A8050203CEF6800D25F23 /* CoreObjC */,
- 63648C94203CB97400EBA011 /* DeprecationTests.swift */,
- );
- name = Tests;
- sourceTree = "";
- };
- 6399A3711D595D9100D65233 = {
- isa = PBXGroup;
- children = (
- 635893971D5BE4F900F14B55 /* README.md */,
- 635893921D5BE4E000F14B55 /* PromiseKit.playground */,
- 63B0AC761D595E6300FA21D9 /* PromiseKit.h */,
- 63B0AC601D595E4C00FA21D9 /* Sources.swift */,
- 63B912AB1F1E657400D49110 /* Sources.objc */,
- 635D64061D59630200BC0AF5 /* Tests */,
- 635893991D5BE51700F14B55 /* … */,
- );
- sourceTree = "";
- };
- 63B0AC581D595E1B00FA21D9 /* Products */ = {
- isa = PBXGroup;
- children = (
- 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */,
- 630019221D596292003B4E30 /* PMKCoreTests.xctest */,
- 631751A81D59766500A9DDDC /* PMKA+Tests.xctest */,
- 6314113C1D59795700E24B9E /* PMKBridgeTests.xctest */,
- 633027EA203CC0060037E136 /* PMKDeprecatedTests.xctest */,
- C0244E622047A6CB00ACB4AC /* PMKJSA+Tests.xctest */,
- );
- name = Products;
- sourceTree = "";
- };
- 63B0AC601D595E4C00FA21D9 /* Sources.swift */ = {
- isa = PBXGroup;
- children = (
- 636A29191F1C156B001229C2 /* Promise.swift */,
- 636A29221F1C17A6001229C2 /* Guarantee.swift */,
- 636A29201F1C1716001229C2 /* Thenable.swift */,
- 632FBBE21F33B273008F8FBB /* Catchable.swift */,
- 63B912AC1F1E663E00D49110 /* Features */,
- 63B0AC691D595E6300FA21D9 /* Error.swift */,
- 636A29261F1C3927001229C2 /* Resolver.swift */,
- 636A291E1F1C16FF001229C2 /* Box.swift */,
- 6330B5E01F2E991200D60528 /* Configuration.swift */,
- 63B18AEB1F2D205C00B79E37 /* CustomStringConvertible.swift */,
- 63D9B2F020338D5D0075C00B /* Deprecations.swift */,
- 085B96BE21A9B37C00E5E22F /* LogEvent.swift */,
- );
- name = Sources.swift;
- sourceTree = "";
- };
- 63B0AC9D1D595E6E00FA21D9 /* Internal Utilities */ = {
- isa = PBXGroup;
- children = (
- 63B0AC661D595E6300FA21D9 /* AnyPromise+Private.h */,
- 63B0AC6F1D595E6300FA21D9 /* NSMethodSignatureForBlock.m */,
- 63B0AC711D595E6300FA21D9 /* PMKCallVariadicBlock.m */,
- );
- name = "Internal Utilities";
- sourceTree = "";
- };
- 63B912AB1F1E657400D49110 /* Sources.objc */ = {
- isa = PBXGroup;
- children = (
- 63B0AC641D595E6300FA21D9 /* AnyPromise.m */,
- 63B0AC651D595E6300FA21D9 /* AnyPromise.swift */,
- 63B0AC671D595E6300FA21D9 /* dispatch_promise.m */,
- 630B60C01F2F73B000A1AEFE /* Headers */,
- 630B60BF1F2F739E00A1AEFE /* Features */,
- 63B0AC9D1D595E6E00FA21D9 /* Internal Utilities */,
- );
- name = Sources.objc;
- sourceTree = "";
- };
- 63B912AC1F1E663E00D49110 /* Features */ = {
- isa = PBXGroup;
- children = (
- 0CC3AF2A1FCF84F7000E98C9 /* hang.swift */,
- 63B0AC621D595E6300FA21D9 /* after.swift */,
- 63B912A91F1D7B1300D49110 /* firstly.swift */,
- 636A29241F1C3089001229C2 /* race.swift */,
- 63B0AC7D1D595E6300FA21D9 /* when.swift */,
- );
- name = Features;
- sourceTree = "";
- };
- C0244E6B2047ACAF00ACB4AC /* JS/A+ */ = {
- isa = PBXGroup;
- children = (
- C0244E682047AC9F00ACB4AC /* AllTests.swift */,
- C013F7372048E3B6006B57B1 /* MockNodeEnvironment.swift */,
- C013F7392049076A006B57B1 /* JSPromise.swift */,
- C013F73B20494291006B57B1 /* JSAdapter.swift */,
- C013F73F204E5063006B57B1 /* JSUtils.swift */,
- );
- name = "JS/A+";
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXHeadersBuildPhase section */
- 63B0AC541D595E1B00FA21D9 /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 63B0AC931D595E6300FA21D9 /* PromiseKit.h in Headers */,
- 634AAD2B1EAE517C00B17855 /* fwd.h in Headers */,
- 63B0AC811D595E6300FA21D9 /* AnyPromise.h in Headers */,
- 63B0AC841D595E6300FA21D9 /* AnyPromise+Private.h in Headers */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXHeadersBuildPhase section */
-
-/* Begin PBXNativeTarget section */
- 630019011D596292003B4E30 /* PMKCoreTests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 6300191F1D596292003B4E30 /* Build configuration list for PBXNativeTarget "PMKCoreTests" */;
- buildPhases = (
- 630019021D596292003B4E30 /* Sources */,
- 630019181D596292003B4E30 /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- 635D64051D5962F900BC0AF5 /* PBXTargetDependency */,
- );
- name = PMKCoreTests;
- productName = PromiseKit;
- productReference = 630019221D596292003B4E30 /* PMKCoreTests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- 631411321D59795700E24B9E /* PMKBridgeTests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 631411391D59795700E24B9E /* Build configuration list for PBXNativeTarget "PMKBridgeTests" */;
- buildPhases = (
- 631411351D59795700E24B9E /* Sources */,
- 631411371D59795700E24B9E /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- 631411331D59795700E24B9E /* PBXTargetDependency */,
- );
- name = PMKBridgeTests;
- productName = PromiseKit;
- productReference = 6314113C1D59795700E24B9E /* PMKBridgeTests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- 6317518B1D59766500A9DDDC /* PMKA+Tests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 631751A51D59766500A9DDDC /* Build configuration list for PBXNativeTarget "PMKA+Tests" */;
- buildPhases = (
- 6317518E1D59766500A9DDDC /* Sources */,
- 631751A31D59766500A9DDDC /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- 6317518C1D59766500A9DDDC /* PBXTargetDependency */,
- );
- name = "PMKA+Tests";
- productName = PromiseKit;
- productReference = 631751A81D59766500A9DDDC /* PMKA+Tests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- 633027E0203CC0060037E136 /* PMKDeprecatedTests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 633027E7203CC0060037E136 /* Build configuration list for PBXNativeTarget "PMKDeprecatedTests" */;
- buildPhases = (
- 633027E3203CC0060037E136 /* Sources */,
- 633027E5203CC0060037E136 /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- 633027E1203CC0060037E136 /* PBXTargetDependency */,
- );
- name = PMKDeprecatedTests;
- productName = PromiseKit;
- productReference = 633027EA203CC0060037E136 /* PMKDeprecatedTests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
- 63B0AC561D595E1B00FA21D9 /* PromiseKit */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 63B0AC5F1D595E1B00FA21D9 /* Build configuration list for PBXNativeTarget "PromiseKit" */;
- buildPhases = (
- 63B0AC521D595E1B00FA21D9 /* Sources */,
- 63B0AC531D595E1B00FA21D9 /* Frameworks */,
- 63B0AC541D595E1B00FA21D9 /* Headers */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = PromiseKit;
- productName = PromiseKit;
- productReference = 63B0AC571D595E1B00FA21D9 /* PromiseKit.framework */;
- productType = "com.apple.product-type.framework";
- };
- C0244E4E2047A6CB00ACB4AC /* PMKJSA+Tests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = C0244E5F2047A6CB00ACB4AC /* Build configuration list for PBXNativeTarget "PMKJSA+Tests" */;
- buildPhases = (
- C0244E512047A6CB00ACB4AC /* Sources */,
- C0244E5D2047A6CB00ACB4AC /* Frameworks */,
- C0244E6E2047AF0B00ACB4AC /* CopyFiles */,
- );
- buildRules = (
- );
- dependencies = (
- C0244E4F2047A6CB00ACB4AC /* PBXTargetDependency */,
- );
- name = "PMKJSA+Tests";
- productName = PromiseKit;
- productReference = C0244E622047A6CB00ACB4AC /* PMKJSA+Tests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 6399A3721D595D9100D65233 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 1250;
- TargetAttributes = {
- 630019011D596292003B4E30 = {
- LastSwiftMigration = 1100;
- };
- 631411321D59795700E24B9E = {
- LastSwiftMigration = 1100;
- };
- 6317518B1D59766500A9DDDC = {
- LastSwiftMigration = 1100;
- };
- 633027E0203CC0060037E136 = {
- LastSwiftMigration = 1100;
- };
- 63B0AC561D595E1B00FA21D9 = {
- CreatedOnToolsVersion = 8.0;
- LastSwiftMigration = 1100;
- ProvisioningStyle = Automatic;
- };
- C0244E4E2047A6CB00ACB4AC = {
- LastSwiftMigration = 1100;
- };
- };
- };
- buildConfigurationList = 6399A3751D595D9100D65233 /* Build configuration list for PBXProject "PromiseKit" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = en;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = 6399A3711D595D9100D65233;
- productRefGroup = 63B0AC581D595E1B00FA21D9 /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 63B0AC561D595E1B00FA21D9 /* PromiseKit */,
- 6317518B1D59766500A9DDDC /* PMKA+Tests */,
- 631411321D59795700E24B9E /* PMKBridgeTests */,
- 630019011D596292003B4E30 /* PMKCoreTests */,
- 633027E0203CC0060037E136 /* PMKDeprecatedTests */,
- C0244E4E2047A6CB00ACB4AC /* PMKJSA+Tests */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXSourcesBuildPhase section */
- 630019021D596292003B4E30 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 0C42F31B1FCF86320051309C /* HangTests.swift in Sources */,
- 635D641E1D59635300BC0AF5 /* CancellableErrorTests.swift in Sources */,
- 630A8056203CEF6800D25F23 /* AnyPromiseTests.m in Sources */,
- 635D64221D59635300BC0AF5 /* ZalgoTests.swift in Sources */,
- 635D64271D59635300BC0AF5 /* RaceTests.swift in Sources */,
- 632FBBE51F33B338008F8FBB /* CatchableTests.swift in Sources */,
- 63CF6D80203CD19200EC8927 /* ThenableTests.swift in Sources */,
- 635D642B1D59635300BC0AF5 /* StressTests.swift in Sources */,
- 630A805A203CEF6800D25F23 /* WhenTests.m in Sources */,
- 630A805B203CF67800D25F23 /* DefaultDispatchQueueTests.swift in Sources */,
- 635D641D1D59635300BC0AF5 /* PromiseTests.swift in Sources */,
- 63CF6D7C203CCDAB00EC8927 /* GuaranteeTests.swift in Sources */,
- 639BF757203DF03100FA577B /* Utilities.swift in Sources */,
- 635D64261D59635300BC0AF5 /* WhenResolvedTests.swift in Sources */,
- 635D64231D59635300BC0AF5 /* AfterTests.swift in Sources */,
- 63CF6D7A203CC66000EC8927 /* ErrorTests.swift in Sources */,
- 49A5584D1DC5185900E4D01B /* ResolverTests.swift in Sources */,
- 630A8057203CEF6800D25F23 /* PMKManifoldTests.m in Sources */,
- 085B96B321A6359500E5E22F /* LoggingTests.swift in Sources */,
- 63B7C94B203E2B8200FBEC00 /* AnyPromiseTests.swift in Sources */,
- 630A8059203CEF6800D25F23 /* HangTests.m in Sources */,
- 635D642A1D59635300BC0AF5 /* WhenTests.swift in Sources */,
- 630A8058203CEF6800D25F23 /* JoinTests.m in Sources */,
- 635D64281D59635300BC0AF5 /* WhenConcurrentTests.swift in Sources */,
- 635D642C1D59635300BC0AF5 /* RegressionTests.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 631411351D59795700E24B9E /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 631411461D59797100E24B9E /* Infrastructure.swift in Sources */,
- 631411431D59797100E24B9E /* BridgingTests.m in Sources */,
- 631411441D59797100E24B9E /* BridgingTests.swift in Sources */,
- 631411451D59797100E24B9E /* Infrastructure.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6317518E1D59766500A9DDDC /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 631751C11D59768200A9DDDC /* 2.3.4.swift in Sources */,
- 631751BA1D59768200A9DDDC /* 2.2.2.swift in Sources */,
- 631751BF1D59768200A9DDDC /* 2.3.1.swift in Sources */,
- 631751B91D59768200A9DDDC /* 2.1.3.swift in Sources */,
- 631751BD1D59768200A9DDDC /* 2.2.6.swift in Sources */,
- 631751B71D59768200A9DDDC /* 0.0.0.swift in Sources */,
- 631751C01D59768200A9DDDC /* 2.3.2.swift in Sources */,
- 631751B81D59768200A9DDDC /* 2.1.2.swift in Sources */,
- 631751BE1D59768200A9DDDC /* 2.2.7.swift in Sources */,
- 631751BC1D59768200A9DDDC /* 2.2.4.swift in Sources */,
- 631751BB1D59768200A9DDDC /* 2.2.3.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 633027E3203CC0060037E136 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 63CF6D7E203CD12700EC8927 /* DeprecationTests.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 63B0AC521D595E1B00FA21D9 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 636A29251F1C3089001229C2 /* race.swift in Sources */,
- 63B0AC9A1D595E6300FA21D9 /* when.swift in Sources */,
- 636A29271F1C3927001229C2 /* Resolver.swift in Sources */,
- 63B0AC991D595E6300FA21D9 /* when.m in Sources */,
- 63D9B2EF203385FD0075C00B /* race.m in Sources */,
- 63B0AC801D595E6300FA21D9 /* after.swift in Sources */,
- 63B18AEC1F2D205C00B79E37 /* CustomStringConvertible.swift in Sources */,
- 085B96BF21A9B37C00E5E22F /* LogEvent.swift in Sources */,
- 6330B5E11F2E991200D60528 /* Configuration.swift in Sources */,
- 63B912AA1F1D7B1300D49110 /* firstly.swift in Sources */,
- 636A29211F1C1716001229C2 /* Thenable.swift in Sources */,
- 632FBBE31F33B273008F8FBB /* Catchable.swift in Sources */,
- 63B0AC851D595E6300FA21D9 /* dispatch_promise.m in Sources */,
- 636A291F1F1C16FF001229C2 /* Box.swift in Sources */,
- 63B0AC821D595E6300FA21D9 /* AnyPromise.m in Sources */,
- 636A29231F1C17A6001229C2 /* Guarantee.swift in Sources */,
- 636A291A1F1C156B001229C2 /* Promise.swift in Sources */,
- 63B0AC8B1D595E6300FA21D9 /* join.m in Sources */,
- 63B0AC891D595E6300FA21D9 /* hang.m in Sources */,
- 63B0AC831D595E6300FA21D9 /* AnyPromise.swift in Sources */,
- 63D9B2F120338D5D0075C00B /* Deprecations.swift in Sources */,
- 63B0AC871D595E6300FA21D9 /* Error.swift in Sources */,
- 0CC3AF2B1FCF84F7000E98C9 /* hang.swift in Sources */,
- 63B0AC7F1D595E6300FA21D9 /* after.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- C0244E512047A6CB00ACB4AC /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- C013F73C20494291006B57B1 /* JSAdapter.swift in Sources */,
- C0244E692047AC9F00ACB4AC /* AllTests.swift in Sources */,
- C013F740204E5064006B57B1 /* JSUtils.swift in Sources */,
- C013F73A2049076A006B57B1 /* JSPromise.swift in Sources */,
- C013F7382048E3B6006B57B1 /* MockNodeEnvironment.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
- 631411331D59795700E24B9E /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 63B0AC561D595E1B00FA21D9 /* PromiseKit */;
- targetProxy = 631411341D59795700E24B9E /* PBXContainerItemProxy */;
- };
- 6317518C1D59766500A9DDDC /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 63B0AC561D595E1B00FA21D9 /* PromiseKit */;
- targetProxy = 6317518D1D59766500A9DDDC /* PBXContainerItemProxy */;
- };
- 633027E1203CC0060037E136 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 63B0AC561D595E1B00FA21D9 /* PromiseKit */;
- targetProxy = 633027E2203CC0060037E136 /* PBXContainerItemProxy */;
- };
- 635D64051D5962F900BC0AF5 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 63B0AC561D595E1B00FA21D9 /* PromiseKit */;
- targetProxy = 635D64041D5962F900BC0AF5 /* PBXContainerItemProxy */;
- };
- C0244E4F2047A6CB00ACB4AC /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 63B0AC561D595E1B00FA21D9 /* PromiseKit */;
- targetProxy = C0244E502047A6CB00ACB4AC /* PBXContainerItemProxy */;
- };
-/* End PBXTargetDependency section */
-
-/* Begin XCBuildConfiguration section */
- 630019201D596292003B4E30 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
- SWIFT_INSTALL_OBJC_HEADER = NO;
- TVOS_DEPLOYMENT_TARGET = 10.1;
- };
- name = Debug;
- };
- 630019211D596292003B4E30 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
- SWIFT_INSTALL_OBJC_HEADER = NO;
- TVOS_DEPLOYMENT_TARGET = 10.1;
- };
- name = Release;
- };
- 6314113A1D59795700E24B9E /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- SWIFT_OBJC_BRIDGING_HEADER = Tests/Bridging/Infrastructure.h;
- };
- name = Debug;
- };
- 6314113B1D59795700E24B9E /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- SWIFT_OBJC_BRIDGING_HEADER = Tests/Bridging/Infrastructure.h;
- };
- name = Release;
- };
- 631751A61D59766500A9DDDC /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- };
- name = Debug;
- };
- 631751A71D59766500A9DDDC /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- };
- name = Release;
- };
- 633027E8203CC0060037E136 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- SWIFT_SUPPRESS_WARNINGS = YES;
- };
- name = Debug;
- };
- 633027E9203CC0060037E136 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- SWIFT_SUPPRESS_WARNINGS = YES;
- };
- name = Release;
- };
- 6399A3761D595D9100D65233 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 6.15.3;
- DEBUG_INFORMATION_FORMAT = dwarf;
- DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
- LD_DYLIB_INSTALL_NAME = "@rpath";
- MACOSX_DEPLOYMENT_TARGET = 10.10;
- ONLY_ACTIVE_ARCH = YES;
- PRODUCT_BUNDLE_IDENTIFIER = org.promisekit;
- PRODUCT_BUNDLE_PACKAGE_TYPE = BNDL;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SUPPORTED_PLATFORMS = "macosx appletvsimulator appletvos watchsimulator iphonesimulator watchos iphoneos";
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
- TVOS_DEPLOYMENT_TARGET = 9.0;
- VERSIONING_SYSTEM = "apple-generic";
- WATCHOS_DEPLOYMENT_TARGET = 2.0;
- };
- name = Debug;
- };
- 6399A3771D595D9100D65233 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 6.15.3;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1;
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
- LD_DYLIB_INSTALL_NAME = "@rpath";
- MACOSX_DEPLOYMENT_TARGET = 10.10;
- PRODUCT_BUNDLE_IDENTIFIER = org.promisekit;
- PRODUCT_BUNDLE_PACKAGE_TYPE = BNDL;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SUPPORTED_PLATFORMS = "macosx appletvsimulator appletvos watchsimulator iphonesimulator watchos iphoneos";
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
- SWIFT_VERSION = 4.0;
- TVOS_DEPLOYMENT_TARGET = 9.0;
- VERSIONING_SYSTEM = "apple-generic";
- WATCHOS_DEPLOYMENT_TARGET = 2.0;
- };
- name = Release;
- };
- 63B0AC5D1D595E1B00FA21D9 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- APPLICATION_EXTENSION_API_ONLY = YES;
- CLANG_WARN_ASSIGN_ENUM = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_CXX0X_EXTENSIONS = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
- CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
- CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
- CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
- CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
- DEFINES_MODULE = YES;
- DYLIB_INSTALL_NAME_BASE = "@rpath";
- ENABLE_TESTABILITY = YES;
- GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
- GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
- GCC_TREAT_WARNINGS_AS_ERRORS = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
- GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
- GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
- GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
- GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
- GCC_WARN_SIGN_COMPARE = YES;
- GCC_WARN_STRICT_SELECTOR_MATCH = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNKNOWN_PRAGMAS = YES;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_LABEL = YES;
- GCC_WARN_UNUSED_PARAMETER = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_PACKAGE_TYPE = FMWK;
- SKIP_INSTALL = YES;
- SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;
- TARGETED_DEVICE_FAMILY = "1,2,3,4";
- };
- name = Debug;
- };
- 63B0AC5E1D595E1B00FA21D9 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- APPLICATION_EXTENSION_API_ONLY = YES;
- BITCODE_GENERATION_MODE = bitcode;
- CLANG_WARN_ASSIGN_ENUM = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_CXX0X_EXTENSIONS = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
- CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
- CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
- CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
- CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
- DEFINES_MODULE = YES;
- DYLIB_INSTALL_NAME_BASE = "@rpath";
- GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
- GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
- GCC_TREAT_WARNINGS_AS_ERRORS = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
- GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
- GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
- GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
- GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
- GCC_WARN_SIGN_COMPARE = YES;
- GCC_WARN_STRICT_SELECTOR_MATCH = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNKNOWN_PRAGMAS = YES;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_LABEL = YES;
- GCC_WARN_UNUSED_PARAMETER = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- PRODUCT_BUNDLE_PACKAGE_TYPE = FMWK;
- SKIP_INSTALL = YES;
- SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;
- TARGETED_DEVICE_FAMILY = "1,2,3,4";
- };
- name = Release;
- };
- C0244E602047A6CB00ACB4AC /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CLANG_ENABLE_MODULES = YES;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- };
- name = Debug;
- };
- C0244E612047A6CB00ACB4AC /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CLANG_ENABLE_MODULES = YES;
- LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks @loader_path/Frameworks";
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_INSTALL_OBJC_HEADER = NO;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 6300191F1D596292003B4E30 /* Build configuration list for PBXNativeTarget "PMKCoreTests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 630019201D596292003B4E30 /* Debug */,
- 630019211D596292003B4E30 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 631411391D59795700E24B9E /* Build configuration list for PBXNativeTarget "PMKBridgeTests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 6314113A1D59795700E24B9E /* Debug */,
- 6314113B1D59795700E24B9E /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 631751A51D59766500A9DDDC /* Build configuration list for PBXNativeTarget "PMKA+Tests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 631751A61D59766500A9DDDC /* Debug */,
- 631751A71D59766500A9DDDC /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 633027E7203CC0060037E136 /* Build configuration list for PBXNativeTarget "PMKDeprecatedTests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 633027E8203CC0060037E136 /* Debug */,
- 633027E9203CC0060037E136 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 6399A3751D595D9100D65233 /* Build configuration list for PBXProject "PromiseKit" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 6399A3761D595D9100D65233 /* Debug */,
- 6399A3771D595D9100D65233 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 63B0AC5F1D595E1B00FA21D9 /* Build configuration list for PBXNativeTarget "PromiseKit" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 63B0AC5D1D595E1B00FA21D9 /* Debug */,
- 63B0AC5E1D595E1B00FA21D9 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- C0244E5F2047A6CB00ACB4AC /* Build configuration list for PBXNativeTarget "PMKJSA+Tests" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- C0244E602047A6CB00ACB4AC /* Debug */,
- C0244E612047A6CB00ACB4AC /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 6399A3721D595D9100D65233 /* Project object */;
-}
diff --git a/PromiseKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PromiseKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 919434a62..000000000
--- a/PromiseKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d981003..000000000
--- a/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 08de0be8d..000000000
--- a/PromiseKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
-
-
-
diff --git a/PromiseKit.xcodeproj/xcshareddata/xcschemes/PromiseKit.xcscheme b/PromiseKit.xcodeproj/xcshareddata/xcschemes/PromiseKit.xcscheme
deleted file mode 100644
index 288d4a273..000000000
--- a/PromiseKit.xcodeproj/xcshareddata/xcschemes/PromiseKit.xcscheme
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/README.md b/README.md
index d4b675d84..ce07db9b4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@

-[![badge-pod][]][cocoapods] ![badge-languages][] ![badge-pms][] ![badge-platforms][] [![badge-travis][]][travis]
+![badge-languages][] ![badge-platforms][]
---
@@ -27,43 +27,30 @@ firstly {
```
PromiseKit is a thoughtful and complete implementation of promises for any
-platform that has a `swiftc`. It has *excellent* Objective-C bridging and
+platform that has a `swiftc`. It has
*delightful* specializations for iOS, macOS, tvOS and watchOS. It is a top-100
pod used in many of the most popular apps in the world.
[](https://codecov.io/gh/mxcl/PromiseKit)
-# PromiseKit 7 Alpha
+# Requirements
-We are testing PromiseKit 7 alpha, it is Swift 5 only. It is tagged and thus
-importable in all package managers.
+Xcode >= 12.0 or Swift >= 5.3.
-# PromiseKit 6
-
-[Release notes and migration guide][PMK6].
+For earlier Swifts, Xcodes or for Objective-C support, use [PromiseKit 6](https://github.com/mxcl/PromiseKit/blob/v6/README.md).
# Quick Start
-In your [Podfile]:
-
-```ruby
-use_frameworks!
+In your `Package.swift`:
-target "Change Me!" do
- pod "PromiseKit", "~> 6.8"
-end
+```swift
+package.dependencies.append(
+ .package(url: "https://github.com/mxcl/PromiseKit", from: "7.0.0-rc1")
+)
```
-> The above gives an Xcode warning? See our [Installation Guide].
-
-PromiseKit 6, 5 and 4 support Xcode 8.3, 9.x and 10.0; Swift 3.1,
-3.2, 3.3, 3.4, 4.0, 4.1, 4.2, 4.3 and 5.0 (development snapshots); iOS, macOS,
-tvOS, watchOS, Linux and Android; CocoaPods, Carthage and SwiftPM;
-([CI Matrix](https://travis-ci.org/mxcl/PromiseKit)).
-
-For Carthage, SwiftPM, Accio, etc., or for instructions when using older Swifts or Xcodes, see our [Installation Guide]. We recommend
-[Carthage](https://github.com/Carthage/Carthage) or
-[Accio](https://github.com/JamitLabs/Accio).
+For more detailed installation instructions or for other package managers see our
+[Installation Guide].
# Professionally Supported PromiseKit is Now Available
@@ -74,118 +61,38 @@ tools.
[Get Professional Support for PromiseKit with TideLift](https://tidelift.com/subscription/pkg/cocoapods-promisekit?utm_source=cocoapods-promisekit&utm_medium=referral&utm_campaign=readme).
-# PromiseKit is Thousands of Hours of Work
+## Other Sponsorship
-Hey there, I’m Max Howell. I’m a prolific producer of open source software and
-probably you already use some of it (I created [`brew`]). I work full-time on
-open source and it’s hard; currently *I earn less than minimum wage*. Please
-help me continue my work, I appreciate it 🙏🏻
-
-
-
-
-
-[Other ways to say thanks](http://mxcl.dev/#donate).
-
-[`brew`]: https://brew.sh
+Maintaining this project is work, if your company uses this project please
+sponsor it either via Tidelift or GitHub Sponsors.
# Documentation
* Handbook
- * [Getting Started](Documentation/GettingStarted.md)
- * [Promises: Common Patterns](Documentation/CommonPatterns.md)
- * [Frequently Asked Questions](Documentation/FAQ.md)
+ * [Getting Started](Documents/GettingStarted.md)
+ * [Promises: Common Patterns](Documents/CommonPatterns.md)
+ * [Cancelling Promises](Documents/Cancel.md)
+ * [Frequently Asked Questions](Documents/FAQ.md)
* Manual
- * [Installation Guide](Documentation/Installation.md)
- * [Objective-C Guide](Documentation/ObjectiveC.md)
- * [Troubleshooting](Documentation/Troubleshooting.md) (e.g., solutions to common compile errors)
- * [Appendix](Documentation/Appendix.md)
-* [API Reference](https://mxcl.dev/PromiseKit/reference/v6/Classes/Promise.html)
+ * [Installation Guide](Documents/Installation.md)
+ * [Troubleshooting](Documents/Troubleshooting.md) (e.g., solutions to common compile errors)
+ * [Appendix](Documents/Appendix.md)
+* [API Reference](https://mxcl.dev/PromiseKit/reference/v7/Classes/Promise.html)
# Extensions
Promises are only as useful as the asynchronous tasks they represent. Thus, we
-have converted (almost) all of Apple’s APIs to promises. The default CocoaPod
-provides Promises and the extensions for Foundation and UIKit. The other
-extensions are available by specifying additional subspecs in your `Podfile`,
-e.g.:
-
-```ruby
-pod "PromiseKit/MapKit" # MKDirections().calculate().then { /*…*/ }
-pod "PromiseKit/CoreLocation" # CLLocationManager.requestLocation().then { /*…*/ }
-```
-
-All our extensions are separate repositories at the [PromiseKit organization].
-
-## I don't want the extensions!
-
-Then don’t have them:
-
-```ruby
-pod "PromiseKit/CorePromise", "~> 6.8"
-```
-
-> *Note:* Carthage installations come with no extensions by default.
-
-## Choose Your Networking Library
-
-Promise chains commonly start with a network operation. Thus, we offer
-extensions for `URLSession`:
-
-```swift
-// pod 'PromiseKit/Foundation' # https://github.com/PromiseKit/Foundation
-
-firstly {
- URLSession.shared.dataTask(.promise, with: try makeUrlRequest()).validate()
- // ^^ we provide `.validate()` so that eg. 404s get converted to errors
-}.map {
- try JSONDecoder().decode(Foo.self, with: $0.data)
-}.done { foo in
- //…
-}.catch { error in
- //…
-}
-
-func makeUrlRequest() throws -> URLRequest {
- var rq = URLRequest(url: url)
- rq.httpMethod = "POST"
- rq.addValue("application/json", forHTTPHeaderField: "Content-Type")
- rq.addValue("application/json", forHTTPHeaderField: "Accept")
- rq.httpBody = try JSONEncoder().encode(obj)
- return rq
-}
-```
-
-And [Alamofire]:
-
-```swift
-// pod 'PromiseKit/Alamofire' # https://github.com/PromiseKit/Alamofire-
-
-firstly {
- Alamofire
- .request("http://example.com", method: .post, parameters: params)
- .responseDecodable(Foo.self)
-}.done { foo in
- //…
-}.catch { error in
- //…
-}
-```
-
-Nowadays, considering that:
+have converted (almost) all of Apple’s APIs to promises. You can use the
+extensions by adding the appropriate library to your `Package.swift` and then
+importing it (eg. `import PMKFoundation`).
-* We almost always POST JSON
-* We now have `JSONDecoder`
-* PromiseKit now has `map` and other functional primitives
-* PromiseKit (like Alamofire, but not raw-`URLSession`) also defaults to having
- callbacks go to the main thread
+See our [Installation Guide](Documents/Installation.md) for usage details.
-We recommend vanilla `URLSession`. It uses fewer black boxes and sticks closer to the metal. Alamofire was essential until the three bullet points above
-became true, but nowadays it isn’t really necessary.
+Browse the `Sources` folder here for a list of available extensions.
# Support
-Please check our [Troubleshooting Guide](Documentation/Troubleshooting.md), and
+Please check our [Troubleshooting Guide](Documents/Troubleshooting.md), and
if after that you still have a question, ask at our [Gitter chat channel] or on [our bug tracker].
## Security & Vulnerability Reporting or Disclosure
@@ -195,7 +102,7 @@ https://tidelift.com/security
[badge-pod]: https://img.shields.io/cocoapods/v/PromiseKit.svg?label=version
[badge-pms]: https://img.shields.io/badge/supports-CocoaPods%20%7C%20Carthage%20%7C%20Accio%20%7C%20SwiftPM-green.svg
-[badge-languages]: https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg
+[badge-languages]: https://img.shields.io/badge/languages-Swift-orange.svg
[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20watchOS%20%7C%20tvOS%20%7C%20Linux-lightgrey.svg
[badge-mit]: https://img.shields.io/badge/license-MIT-blue.svg
[OMGHTTPURLRQ]: https://github.com/PromiseKit/OMGHTTPURLRQ
@@ -205,7 +112,7 @@ https://tidelift.com/security
[our bug tracker]: https://github.com/mxcl/PromiseKit/issues/new
[Podfile]: https://guides.cocoapods.org/syntax/podfile.html
[PMK6]: http://mxcl.dev/PromiseKit/news/2018/02/PromiseKit-6.0-Released/
-[Installation Guide]: Documentation/Installation.md
+[Installation Guide]: Documents/Installation.md
[badge-travis]: https://travis-ci.org/mxcl/PromiseKit.svg?branch=master
[travis]: https://travis-ci.org/mxcl/PromiseKit
[cocoapods]: https://cocoapods.org/pods/PromiseKit
diff --git a/Sources/AnyPromise+Private.h b/Sources/AnyPromise+Private.h
deleted file mode 100644
index cd28c4183..000000000
--- a/Sources/AnyPromise+Private.h
+++ /dev/null
@@ -1,32 +0,0 @@
-@import Foundation.NSError;
-@import Foundation.NSPointerArray;
-
-#if TARGET_OS_IPHONE
- #define NSPointerArrayMake(N) ({ \
- NSPointerArray *aa = [NSPointerArray strongObjectsPointerArray]; \
- aa.count = N; \
- aa; \
- })
-#else
- static inline NSPointerArray * __nonnull NSPointerArrayMake(NSUInteger count) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- NSPointerArray *aa = [[NSPointerArray class] respondsToSelector:@selector(strongObjectsPointerArray)]
- ? [NSPointerArray strongObjectsPointerArray]
- : [NSPointerArray pointerArrayWithStrongObjects];
- #pragma clang diagnostic pop
- aa.count = count;
- return aa;
- }
-#endif
-
-#define IsError(o) [o isKindOfClass:[NSError class]]
-#define IsPromise(o) [o isKindOfClass:[AnyPromise class]]
-
-#import "AnyPromise.h"
-
-@class PMKArray;
-
-@interface AnyPromise ()
-- (void)__pipe:(void(^ __nonnull)(__nullable id))block NS_REFINED_FOR_SWIFT;
-@end
diff --git a/Sources/AnyPromise.h b/Sources/AnyPromise.h
deleted file mode 100644
index 75352d55c..000000000
--- a/Sources/AnyPromise.h
+++ /dev/null
@@ -1,308 +0,0 @@
-#import
-#import
-#import
-
-/// INTERNAL DO NOT USE
-@class __AnyPromise;
-
-/// Provided to simplify some usage sites
-typedef void (^PMKResolver)(id __nullable) NS_REFINED_FOR_SWIFT;
-
-
-/// An Objective-C implementation of the promise pattern.
-@interface AnyPromise: NSObject
-
-/**
- Create a new promise that resolves with the provided block.
-
- Use this method when wrapping asynchronous code that does *not* use promises so that this code can be used in promise chains.
-
- If `resolve` is called with an `NSError` object, the promise is rejected, otherwise the promise is fulfilled.
-
- Don’t use this method if you already have promises! Instead, just return your promise.
-
- Should you need to fulfill a promise but have no sensical value to use: your promise is a `void` promise: fulfill with `nil`.
-
- The block you pass is executed immediately on the calling thread.
-
- - Parameter block: The provided block is immediately executed, inside the block call `resolve` to resolve this promise and cause any attached handlers to execute. If you are wrapping a delegate-based system, we recommend instead to use: initWithResolver:
- - Returns: A new promise.
- - Warning: Resolving a promise with `nil` fulfills it.
- - SeeAlso: https://github.com/mxcl/PromiseKit/blob/master/Documentation/GettingStarted.md#making-promises
- - SeeAlso: https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#wrapping-delegate-systems
- */
-+ (instancetype __nonnull)promiseWithResolverBlock:(void (^ __nonnull)(__nonnull PMKResolver))resolveBlock NS_REFINED_FOR_SWIFT;
-
-
-/// INTERNAL DO NOT USE
-- (instancetype __nonnull)initWith__D:(__AnyPromise * __nonnull)d;
-
-/**
- Creates a 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.
- - Returns: A resolved promise.
- */
-+ (instancetype __nonnull)promiseWithValue:(__nullable id)value NS_REFINED_FOR_SWIFT;
-
-/**
- The value of the asynchronous task this promise represents.
-
- A promise has `nil` value if the asynchronous task it represents has not finished. If the value is `nil` the promise is still `pending`.
-
- - Warning: *Note* Our Swift variant’s value property returns nil if the promise is rejected where AnyPromise will return the error object. This fits with the pattern where AnyPromise is not strictly typed and is more dynamic, but you should be aware of the distinction.
-
- - Note: If the AnyPromise was fulfilled with a `PMKManifold`, returns only the first fulfillment object.
-
- - Returns: The value with which this promise was resolved or `nil` if this promise is pending.
- */
-@property (nonatomic, readonly) __nullable id value NS_REFINED_FOR_SWIFT;
-
-/// - Returns: if the promise is pending resolution.
-@property (nonatomic, readonly) BOOL pending NS_REFINED_FOR_SWIFT;
-
-/// - Returns: if the promise is resolved and fulfilled.
-@property (nonatomic, readonly) BOOL fulfilled NS_REFINED_FOR_SWIFT;
-
-/// - Returns: if the promise is resolved and rejected.
-@property (nonatomic, readonly) BOOL rejected NS_REFINED_FOR_SWIFT;
-
-
-/**
- The provided block is executed when its receiver is fulfilled.
-
- If you provide a block that takes a parameter, the value of the receiver will be passed as that parameter.
-
- [NSURLSession GET:url].then(^(NSData *data){
- // do something with data
- });
-
- @return A new promise that is resolved with the value returned from the provided block. For example:
-
- [NSURLSession GET:url].then(^(NSData *data){
- return data.length;
- }).then(^(NSNumber *number){
- //…
- });
-
- @warning *Important* The block passed to `then` may take zero, one, two or three arguments, and return an object or return nothing. This flexibility is why the method signature for then is `id`, which means you will not get completion for the block parameter, and must type it yourself. It is safe to type any block syntax here, so to start with try just: `^{}`.
-
- @warning *Important* If an `NSError` or `NSString` is thrown inside your block, or you return an `NSError` object the next `Promise` will be rejected. See `catch` for documentation on error handling.
-
- @warning *Important* `then` is always executed on the main queue.
-
- @see thenOn
- @see thenInBackground
-*/
-- (AnyPromise * __nonnull (^ __nonnull)(id __nonnull))then NS_REFINED_FOR_SWIFT;
-
-
-/**
- The provided block is executed on the default queue when the receiver is fulfilled.
-
- This method is provided as a convenience for `thenOn`.
-
- @see then
- @see thenOn
-*/
-- (AnyPromise * __nonnull(^ __nonnull)(id __nonnull))thenInBackground NS_REFINED_FOR_SWIFT;
-
-/**
- The provided block is executed on the dispatch queue of your choice when the receiver is fulfilled.
-
- @see then
- @see thenInBackground
-*/
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_queue_t __nonnull, id __nonnull))thenOn NS_REFINED_FOR_SWIFT;
-
-#ifndef __cplusplus
-/**
- The provided block is executed when the receiver is rejected.
-
- Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either.
-
- The provided block always runs on the main queue.
-
- @warning *Note* Cancellation errors are not caught.
-
- @warning *Note* Since catch is a c++ keyword, this method is not available in Objective-C++ files. Instead use catchOn.
-
- @see catchOn
- @see catchInBackground
-*/
-- (AnyPromise * __nonnull(^ __nonnull)(id __nonnull))catch NS_REFINED_FOR_SWIFT;
-#endif
-
-/**
- The provided block is executed when the receiver is rejected.
-
- Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either.
-
- The provided block always runs on the global background queue.
-
- @warning *Note* Cancellation errors are not caught.
-
- @warning *Note* Since catch is a c++ keyword, this method is not available in Objective-C++ files. Instead use catchWithPolicy.
-
- @see catch
- @see catchOn
- */
-- (AnyPromise * __nonnull(^ __nonnull)(id __nonnull))catchInBackground NS_REFINED_FOR_SWIFT;
-
-
-/**
- The provided block is executed when the receiver is rejected.
-
- Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either.
-
- The provided block always runs on queue provided.
-
- @warning *Note* Cancellation errors are not caught.
-
- @see catch
- @see catchInBackground
- */
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_queue_t __nonnull, id __nonnull))catchOn NS_REFINED_FOR_SWIFT;
-
-/**
- The provided block is executed when the receiver is resolved.
-
- The provided block always runs on the main queue.
-
- @see ensureOn
-*/
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_block_t __nonnull))ensure NS_REFINED_FOR_SWIFT;
-
-/**
- The provided block is executed on the dispatch queue of your choice when the receiver is resolved.
-
- @see ensure
- */
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_queue_t __nonnull, dispatch_block_t __nonnull))ensureOn NS_REFINED_FOR_SWIFT;
-
-/**
- Wait until the promise is resolved.
-
- @return Value if fulfilled or error if rejected.
- */
-- (id __nullable)wait NS_REFINED_FOR_SWIFT;
-
-/**
- Create a new promise with an associated resolver.
-
- Use this method when wrapping asynchronous code that does *not* use
- promises so that this code can be used in promise chains. Generally,
- prefer `promiseWithResolverBlock:` as the resulting code is more elegant.
-
- PMKResolver resolve;
- AnyPromise *promise = [[AnyPromise alloc] initWithResolver:&resolve];
-
- // later
- resolve(@"foo");
-
- @param resolver A reference to a block pointer of PMKResolver type.
- You can then call your resolver to resolve this promise.
-
- @return A new promise.
-
- @warning *Important* The resolver strongly retains the promise.
-
- @see promiseWithResolverBlock:
-*/
-- (instancetype __nonnull)initWithResolver:(PMKResolver __strong __nonnull * __nonnull)resolver NS_REFINED_FOR_SWIFT;
-
-/**
- Unavailable methods
- */
-
-- (instancetype __nonnull)init __attribute__((unavailable("It is illegal to create an unresolvable promise.")));
-+ (instancetype __nonnull)new __attribute__((unavailable("It is illegal to create an unresolvable promise.")));
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_block_t __nonnull))always __attribute__((unavailable("See -ensure")));
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_block_t __nonnull))alwaysOn __attribute__((unavailable("See -ensureOn")));
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_block_t __nonnull))finally __attribute__((unavailable("See -ensure")));
-- (AnyPromise * __nonnull(^ __nonnull)(dispatch_block_t __nonnull, dispatch_block_t __nonnull))finallyOn __attribute__((unavailable("See -ensureOn")));
-
-@end
-
-
-typedef void (^PMKAdapter)(id __nullable, NSError * __nullable) NS_REFINED_FOR_SWIFT;
-typedef void (^PMKIntegerAdapter)(NSInteger, NSError * __nullable) NS_REFINED_FOR_SWIFT;
-typedef void (^PMKBooleanAdapter)(BOOL, NSError * __nullable) NS_REFINED_FOR_SWIFT;
-
-
-@interface AnyPromise (Adapters)
-
-/**
- Create a new promise by adapting an existing asynchronous system.
-
- The pattern of a completion block that passes two parameters, the first
- the result and the second an `NSError` object is so common that we
- provide this convenience adapter to make wrapping such systems more
- elegant.
-
- return [PMKPromise promiseWithAdapterBlock:^(PMKAdapter adapter){
- PFQuery *query = [PFQuery …];
- [query findObjectsInBackgroundWithBlock:adapter];
- }];
-
- @warning *Important* If both parameters are nil, the promise fulfills,
- if both are non-nil the promise rejects. This is per the convention.
-
- @see https://github.com/mxcl/PromiseKit/blob/master/Documentation/GettingStarted.md#making-promises
- */
-+ (instancetype __nonnull)promiseWithAdapterBlock:(void (^ __nonnull)(PMKAdapter __nonnull adapter))block NS_REFINED_FOR_SWIFT;
-
-/**
- Create a new promise by adapting an existing asynchronous system.
-
- Adapts asynchronous systems that complete with `^(NSInteger, NSError *)`.
- NSInteger will cast to enums provided the enum has been wrapped with
- `NS_ENUM`. All of Apple’s enums are, so if you find one that hasn’t you
- may need to make a pull-request.
-
- @see promiseWithAdapter
- */
-+ (instancetype __nonnull)promiseWithIntegerAdapterBlock:(void (^ __nonnull)(PMKIntegerAdapter __nonnull adapter))block NS_REFINED_FOR_SWIFT;
-
-/**
- Create a new promise by adapting an existing asynchronous system.
-
- Adapts asynchronous systems that complete with `^(BOOL, NSError *)`.
-
- @see promiseWithAdapter
- */
-+ (instancetype __nonnull)promiseWithBooleanAdapterBlock:(void (^ __nonnull)(PMKBooleanAdapter __nonnull adapter))block NS_REFINED_FOR_SWIFT;
-
-@end
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- Whenever resolving a promise you may resolve with a tuple, eg.
- returning from a `then` or `catch` handler or resolving a new promise.
-
- Consumers of your Promise are not compelled to consume any arguments and
- in fact will often only consume the first parameter. Thus ensure the
- order of parameters is: from most-important to least-important.
-
- Currently PromiseKit limits you to THREE parameters to the manifold.
-*/
-#define PMKManifold(...) __PMKManifold(__VA_ARGS__, 3, 2, 1)
-#define __PMKManifold(_1, _2, _3, N, ...) __PMKArrayWithCount(N, _1, _2, _3)
-extern id __nonnull __PMKArrayWithCount(NSUInteger, ...);
-
-#ifdef __cplusplus
-} // Extern C
-#endif
-
-
-
-
-__attribute__((unavailable("See AnyPromise")))
-@interface PMKPromise
-@end
diff --git a/Sources/AnyPromise.m b/Sources/AnyPromise.m
deleted file mode 100644
index 3725beacd..000000000
--- a/Sources/AnyPromise.m
+++ /dev/null
@@ -1,179 +0,0 @@
-#if __has_include("PromiseKit-Swift.h")
- #import "PromiseKit-Swift.h"
-#else
- #import
-#endif
-#import "PMKCallVariadicBlock.m"
-#import "AnyPromise+Private.h"
-#import "AnyPromise.h"
-
-NSString *const PMKErrorDomain = @"PMKErrorDomain";
-
-
-@implementation AnyPromise {
- __AnyPromise *d;
-}
-
-- (instancetype)initWith__D:(__AnyPromise *)dd {
- self = [super init];
- if (self) self->d = dd;
- return self;
-}
-
-- (instancetype)initWithResolver:(PMKResolver __strong *)resolver {
- self = [super init];
- if (self)
- d = [[__AnyPromise alloc] initWithResolver:^(void (^resolve)(id)) {
- *resolver = resolve;
- }];
- return self;
-}
-
-+ (instancetype)promiseWithResolverBlock:(void (^)(PMKResolver _Nonnull))resolveBlock {
- id d = [[__AnyPromise alloc] initWithResolver:resolveBlock];
- return [[self alloc] initWith__D:d];
-}
-
-+ (instancetype)promiseWithValue:(id)value {
- //TODO provide a more efficient route for sealed promises
- id d = [[__AnyPromise alloc] initWithResolver:^(void (^resolve)(id)) {
- resolve(value);
- }];
- return [[self alloc] initWith__D:d];
-}
-
-//TODO remove if possible, but used by when.m
-- (void)__pipe:(void (^)(id _Nullable))block {
- [d __pipe:block];
-}
-
-//NOTE used by AnyPromise.swift
-- (id)__d {
- return d;
-}
-
-- (AnyPromise *(^)(id))then {
- return ^(id block) {
- return [self->d __thenOn:dispatch_get_main_queue() execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(dispatch_queue_t, id))thenOn {
- return ^(dispatch_queue_t queue, id block) {
- return [self->d __thenOn:queue execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(id))thenInBackground {
- return ^(id block) {
- return [self->d __thenOn:dispatch_get_global_queue(0, 0) execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(dispatch_queue_t, id))catchOn {
- return ^(dispatch_queue_t q, id block) {
- return [self->d __catchOn:q execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(id))catch {
- return ^(id block) {
- return [self->d __catchOn:dispatch_get_main_queue() execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(id))catchInBackground {
- return ^(id block) {
- return [self->d __catchOn:dispatch_get_global_queue(0, 0) execute:^(id obj) {
- return PMKCallVariadicBlock(block, obj);
- }];
- };
-}
-
-- (AnyPromise *(^)(dispatch_block_t))ensure {
- return ^(dispatch_block_t block) {
- return [self->d __ensureOn:dispatch_get_main_queue() execute:block];
- };
-}
-
-- (AnyPromise *(^)(dispatch_queue_t, dispatch_block_t))ensureOn {
- return ^(dispatch_queue_t queue, dispatch_block_t block) {
- return [self->d __ensureOn:queue execute:block];
- };
-}
-
-- (id)wait {
- return [d __wait];
-}
-
-- (BOOL)pending {
- return [[d valueForKey:@"__pending"] boolValue];
-}
-
-- (BOOL)rejected {
- return IsError([d __value]);
-}
-
-- (BOOL)fulfilled {
- return !self.rejected;
-}
-
-- (id)value {
- id obj = [d __value];
-
- if ([obj isKindOfClass:[PMKArray class]]) {
- return obj[0];
- } else {
- return obj;
- }
-}
-
-@end
-
-
-
-@implementation AnyPromise (Adapters)
-
-+ (instancetype)promiseWithAdapterBlock:(void (^)(PMKAdapter))block {
- return [self promiseWithResolverBlock:^(PMKResolver resolve) {
- block(^(id value, id error){
- resolve(error ?: value);
- });
- }];
-}
-
-+ (instancetype)promiseWithIntegerAdapterBlock:(void (^)(PMKIntegerAdapter))block {
- return [self promiseWithResolverBlock:^(PMKResolver resolve) {
- block(^(NSInteger value, id error){
- if (error) {
- resolve(error);
- } else {
- resolve(@(value));
- }
- });
- }];
-}
-
-+ (instancetype)promiseWithBooleanAdapterBlock:(void (^)(PMKBooleanAdapter adapter))block {
- return [self promiseWithResolverBlock:^(PMKResolver resolve) {
- block(^(BOOL value, id error){
- if (error) {
- resolve(error);
- } else {
- resolve(@(value));
- }
- });
- }];
-}
-
-@end
diff --git a/Sources/AnyPromise.swift b/Sources/AnyPromise.swift
deleted file mode 100644
index d7e575d2d..000000000
--- a/Sources/AnyPromise.swift
+++ /dev/null
@@ -1,224 +0,0 @@
-import Foundation
-
-/**
- __AnyPromise is an implementation detail.
-
- Because of how ObjC/Swift compatibility work we have to compose our AnyPromise
- with this internal object, however this is still part of the public interface.
- Sadly. Please don’t use it.
-*/
-@objc(__AnyPromise) public class __AnyPromise: NSObject {
- fileprivate let box: Box
-
- @objc public init(resolver body: (@escaping (Any?) -> Void) -> Void) {
- box = EmptyBox()
- super.init()
- body {
- if let p = $0 as? AnyPromise {
- p.d.__pipe(self.box.seal)
- } else {
- self.box.seal($0)
- }
- }
- }
-
- @objc public func __thenOn(_ q: DispatchQueue, execute: @escaping (Any?) -> Any?) -> AnyPromise {
- return AnyPromise(__D: __AnyPromise(resolver: { resolve in
- self.__pipe { obj in
- if !(obj is NSError) {
- q.async {
- resolve(execute(obj))
- }
- } else {
- resolve(obj)
- }
- }
- }))
- }
-
- @objc public func __catchOn(_ q: DispatchQueue, execute: @escaping (Any?) -> Any?) -> AnyPromise {
- return AnyPromise(__D: __AnyPromise(resolver: { resolve in
- self.__pipe { obj in
- if obj is NSError {
- q.async {
- resolve(execute(obj))
- }
- } else {
- resolve(obj)
- }
- }
- }))
- }
-
- @objc public func __ensureOn(_ q: DispatchQueue, execute: @escaping () -> Void) -> AnyPromise {
- return AnyPromise(__D: __AnyPromise(resolver: { resolve in
- self.__pipe { obj in
- q.async {
- execute()
- resolve(obj)
- }
- }
- }))
- }
-
- @objc public func __wait() -> Any? {
- if Thread.isMainThread {
- conf.logHandler(.waitOnMainThread)
- }
-
- var result = __value
-
- if result == nil {
- let group = DispatchGroup()
- group.enter()
- self.__pipe { obj in
- result = obj
- group.leave()
- }
- group.wait()
- }
-
- return result
- }
-
- /// Internal, do not use! Some behaviors undefined.
- @objc public func __pipe(_ to: @escaping (Any?) -> Void) {
- let to = { (obj: Any?) -> Void in
- if obj is NSError {
- to(obj) // or we cannot determine if objects are errors in objc land
- } else {
- to(obj)
- }
- }
- switch box.inspect() {
- case .pending:
- box.inspect {
- switch $0 {
- case .pending(let handlers):
- handlers.append { obj in
- to(obj)
- }
- case .resolved(let obj):
- to(obj)
- }
- }
- case .resolved(let obj):
- to(obj)
- }
- }
-
- @objc public var __value: Any? {
- switch box.inspect() {
- case .resolved(let obj):
- return obj
- default:
- return nil
- }
- }
-
- @objc public var __pending: Bool {
- switch box.inspect() {
- case .pending:
- return true
- case .resolved:
- return false
- }
- }
-}
-
-extension AnyPromise: Thenable, CatchMixin {
-
- /// - Returns: A new `AnyPromise` bound to a `Promise`.
- public convenience init(_ bridge: U) {
- self.init(__D: __AnyPromise(resolver: { resolve in
- bridge.pipe {
- switch $0 {
- case .rejected(let error):
- resolve(error as NSError)
- case .fulfilled(let value):
- resolve(value)
- }
- }
- }))
- }
-
- public func pipe(to body: @escaping (Result) -> Void) {
-
- func fulfill() {
- // calling through to the ObjC `value` property unwraps (any) PMKManifold
- // and considering this is the Swift pipe; we want that.
- body(.fulfilled(self.value(forKey: "value")))
- }
-
- switch box.inspect() {
- case .pending:
- box.inspect {
- switch $0 {
- case .pending(let handlers):
- handlers.append {
- if let error = $0 as? Error {
- body(.rejected(error))
- } else {
- fulfill()
- }
- }
- case .resolved(let error as Error):
- body(.rejected(error))
- case .resolved:
- fulfill()
- }
- }
- case .resolved(let error as Error):
- body(.rejected(error))
- case .resolved:
- fulfill()
- }
- }
-
- fileprivate var d: __AnyPromise {
- return value(forKey: "__d") as! __AnyPromise
- }
-
- var box: Box {
- return d.box
- }
-
- public var result: Result? {
- guard let value = __value else {
- return nil
- }
- if let error = value as? Error {
- return .rejected(error)
- } else {
- return .fulfilled(value)
- }
- }
-
- public typealias T = Any?
-}
-
-
-#if swift(>=3.1)
-public extension Promise where T == Any? {
- convenience init(_ anyPromise: AnyPromise) {
- self.init {
- anyPromise.pipe(to: $0.resolve)
- }
- }
-}
-#else
-extension AnyPromise {
- public func asPromise() -> Promise {
- return Promise(.pending, resolver: { resolve in
- pipe { result in
- switch result {
- case .rejected(let error):
- resolve.reject(error)
- case .fulfilled(let obj):
- resolve.fulfill(obj)
- }
- }
- })
- }
-}
-#endif
diff --git a/Sources/Catchable.swift b/Sources/Catchable.swift
deleted file mode 100644
index 596abdcba..000000000
--- a/Sources/Catchable.swift
+++ /dev/null
@@ -1,256 +0,0 @@
-import Dispatch
-
-/// Provides `catch` and `recover` to your object that conforms to `Thenable`
-public protocol CatchMixin: Thenable
-{}
-
-public extension CatchMixin {
-
- /**
- The provided closure executes when this promise rejects.
-
- Rejecting a promise cascades: rejecting all subsequent promises (unless
- recover is invoked) thus you will typically place your catch at the end
- of a chain. Often utility promises will not have a catch, instead
- delegating the error handling to the caller.
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter policy: The default policy does not execute your handler for cancellation errors.
- - Parameter execute: The handler to execute if this promise is rejected.
- - Returns: A promise finalizer.
- - SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
- */
- @discardableResult
- func `catch`(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> PMKFinalizer {
- let finalizer = PMKFinalizer()
- pipe {
- switch $0 {
- case .rejected(let error):
- guard policy == .allErrors || !error.isCancelled else {
- fallthrough
- }
- on.async(flags: flags) {
- body(error)
- finalizer.pending.resolve(())
- }
- case .fulfilled:
- finalizer.pending.resolve(())
- }
- }
- return finalizer
- }
-}
-
-public class PMKFinalizer {
- let pending = Guarantee.pending()
-
- /// `finally` is the same as `ensure`, but it is not chainable
- public func finally(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Void) {
- pending.guarantee.done(on: on, flags: flags) {
- body()
- }
- }
-}
-
-
-public extension CatchMixin {
-
- /**
- The provided closure executes when this promise rejects.
-
- Unlike `catch`, `recover` continues the chain.
- Use `recover` in circumstances where recovering the chain from certain errors is a possibility. For example:
-
- firstly {
- CLLocationManager.requestLocation()
- }.recover { error in
- guard error == CLError.unknownLocation else { throw error }
- return .value(CLLocation.chicago)
- }
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The handler to execute if this promise is rejected.
- - SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
- */
- func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> U) -> Promise where U.T == T {
- let rp = Promise(.pending)
- pipe {
- switch $0 {
- case .fulfilled(let value):
- rp.box.seal(.fulfilled(value))
- case .rejected(let error):
- if policy == .allErrors || !error.isCancelled {
- on.async(flags: flags) {
- do {
- let rv = try body(error)
- guard rv !== rp else { throw PMKError.returnedSelf }
- rv.pipe(to: rp.box.seal)
- } catch {
- rp.box.seal(.rejected(error))
- }
- }
- } else {
- rp.box.seal(.rejected(error))
- }
- }
- }
- return rp
- }
-
- /**
- The provided closure executes when this promise rejects.
- This variant of `recover` requires the handler to return a Guarantee, thus it returns a Guarantee itself and your closure cannot `throw`.
- - Note it is logically impossible for this to take a `catchPolicy`, thus `allErrors` are handled.
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The handler to execute if this promise is rejected.
- - SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
- */
- @discardableResult
- func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Guarantee) -> Guarantee {
- let rg = Guarantee(.pending)
- pipe {
- switch $0 {
- case .fulfilled(let value):
- rg.box.seal(value)
- case .rejected(let error):
- on.async(flags: flags) {
- body(error).pipe(to: rg.box.seal)
- }
- }
- }
- return rg
- }
-
- /**
- The provided closure executes when this promise resolves, whether it rejects or not.
-
- firstly {
- UIApplication.shared.networkActivityIndicatorVisible = true
- }.done {
- //…
- }.ensure {
- UIApplication.shared.networkActivityIndicatorVisible = false
- }.catch {
- //…
- }
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The closure that executes when this promise resolves.
- - Returns: A new promise, resolved with this promise’s resolution.
- */
- func ensure(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Void) -> Promise {
- let rp = Promise(.pending)
- pipe { result in
- on.async(flags: flags) {
- body()
- rp.box.seal(result)
- }
- }
- return rp
- }
-
- /**
- The provided closure executes when this promise resolves, whether it rejects or not.
- The chain waits on the returned `Guarantee`.
-
- firstly {
- setup()
- }.done {
- //…
- }.ensureThen {
- teardown() // -> Guarante
- }.catch {
- //…
- }
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The closure that executes when this promise resolves.
- - Returns: A new promise, resolved with this promise’s resolution.
- */
- func ensureThen(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Guarantee) -> Promise {
- let rp = Promise(.pending)
- pipe { result in
- on.async(flags: flags) {
- body().done {
- rp.box.seal(result)
- }
- }
- }
- return rp
- }
-
-
-
- /**
- Consumes the Swift unused-result warning.
- - Note: You should `catch`, but in situations where you know you don’t need a `catch`, `cauterize` makes your intentions clear.
- */
- @discardableResult
- func cauterize() -> PMKFinalizer {
- return self.catch {
- conf.logHandler(.cauterized($0))
- }
- }
-}
-
-
-public extension CatchMixin where T == Void {
-
- /**
- The provided closure executes when this promise rejects.
-
- This variant of `recover` is specialized for `Void` promises and de-errors your chain returning a `Guarantee`, thus you cannot `throw` and you must handle all errors including cancellation.
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The handler to execute if this promise is rejected.
- - SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
- */
- @discardableResult
- func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Void) -> Guarantee {
- let rg = Guarantee(.pending)
- pipe {
- switch $0 {
- case .fulfilled:
- rg.box.seal(())
- case .rejected(let error):
- on.async(flags: flags) {
- body(error)
- rg.box.seal(())
- }
- }
- }
- return rg
- }
-
- /**
- The provided closure executes when this promise rejects.
-
- This variant of `recover` ensures that no error is thrown from the handler and allows specifying a catch policy.
-
- - Parameter on: The queue to which the provided closure dispatches.
- - Parameter body: The handler to execute if this promise is rejected.
- - SeeAlso: [Cancellation](https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#cancellation)
- */
- func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> Promise {
- let rg = Promise(.pending)
- pipe {
- switch $0 {
- case .fulfilled:
- rg.box.seal(.fulfilled(()))
- case .rejected(let error):
- if policy == .allErrors || !error.isCancelled {
- on.async(flags: flags) {
- do {
- rg.box.seal(.fulfilled(try body(error)))
- } catch {
- rg.box.seal(.rejected(error))
- }
- }
- } else {
- rg.box.seal(.rejected(error))
- }
- }
- }
- return rg
- }
-}
diff --git a/Sources/CustomStringConvertible.swift b/Sources/CustomStringConvertible.swift
deleted file mode 100644
index eee0b020a..000000000
--- a/Sources/CustomStringConvertible.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-
-extension Promise: CustomStringConvertible {
- /// - Returns: A description of the state of this promise.
- public var description: String {
- switch result {
- case nil:
- return "Promise(…\(T.self))"
- case .rejected(let error)?:
- return "Promise(\(error))"
- case .fulfilled(let value)?:
- return "Promise(\(value))"
- }
- }
-}
-
-extension Promise: CustomDebugStringConvertible {
- /// - Returns: A debug-friendly description of the state of this promise.
- public var debugDescription: String {
- switch box.inspect() {
- case .pending(let handlers):
- return "Promise<\(T.self)>.pending(handlers: \(handlers.bodies.count))"
- case .resolved(.rejected(let error)):
- return "Promise<\(T.self)>.rejected(\(type(of: error)).\(error))"
- case .resolved(.fulfilled(let value)):
- return "Promise<\(T.self)>.fulfilled(\(value))"
- }
- }
-}
-
-#if !SWIFT_PACKAGE
-extension AnyPromise {
- /// - Returns: A description of the state of this promise.
- override open var description: String {
- switch box.inspect() {
- case .pending:
- return "AnyPromise(…)"
- case .resolved(let obj?):
- return "AnyPromise(\(obj))"
- case .resolved(nil):
- return "AnyPromise(nil)"
- }
- }
-}
-#endif
diff --git a/Sources/Deprecations.swift b/Sources/Deprecations.swift
deleted file mode 100644
index a837dcb8d..000000000
--- a/Sources/Deprecations.swift
+++ /dev/null
@@ -1,93 +0,0 @@
-import Dispatch
-
-@available(*, deprecated, message: "See `init(resolver:)`")
-public func wrap(_ body: (@escaping (T?, Error?) -> Void) throws -> Void) -> Promise {
- return Promise { seal in
- try body(seal.resolve)
- }
-}
-
-@available(*, deprecated, message: "See `init(resolver:)`")
-public func wrap(_ body: (@escaping (T, Error?) -> Void) throws -> Void) -> Promise {
- return Promise { seal in
- try body(seal.resolve)
- }
-}
-
-@available(*, deprecated, message: "See `init(resolver:)`")
-public func wrap(_ body: (@escaping (Error?, T?) -> Void) throws -> Void) -> Promise {
- return Promise { seal in
- try body(seal.resolve)
- }
-}
-
-@available(*, deprecated, message: "See `init(resolver:)`")
-public func wrap(_ body: (@escaping (Error?) -> Void) throws -> Void) -> Promise {
- return Promise { seal in
- try body(seal.resolve)
- }
-}
-
-@available(*, deprecated, message: "See `init(resolver:)`")
-public func wrap(_ body: (@escaping (T) -> Void) throws -> Void) -> Promise {
- return Promise { seal in
- try body(seal.fulfill)
- }
-}
-
-public extension Promise {
- @available(*, deprecated, message: "See `ensure`")
- func always(on q: DispatchQueue = .main, execute body: @escaping () -> Void) -> Promise {
- return ensure(on: q, body)
- }
-}
-
-public extension Thenable {
-#if PMKFullDeprecations
- /// disabled due to ambiguity with the other `.flatMap`
- @available(*, deprecated, message: "See: `compactMap`")
- func flatMap(on: DispatchQueue? = conf.Q.map, _ transform: @escaping(T) throws -> U?) -> Promise {
- return compactMap(on: on, transform)
- }
-#endif
-}
-
-public extension Thenable where T: Sequence {
-#if PMKFullDeprecations
- /// disabled due to ambiguity with the other `.map`
- @available(*, deprecated, message: "See: `mapValues`")
- func map(on: DispatchQueue? = conf.Q.map, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U]> {
- return mapValues(on: on, transform)
- }
-
- /// disabled due to ambiguity with the other `.flatMap`
- @available(*, deprecated, message: "See: `flatMapValues`")
- func flatMap(on: DispatchQueue? = conf.Q.map, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U.Iterator.Element]> {
- return flatMapValues(on: on, transform)
- }
-#endif
-
- @available(*, deprecated, message: "See: `filterValues`")
- func filter(on: DispatchQueue? = conf.Q.map, test: @escaping (T.Iterator.Element) -> Bool) -> Promise<[T.Iterator.Element]> {
- return filterValues(on: on, test)
- }
-}
-
-public extension Thenable where T: Collection {
- @available(*, deprecated, message: "See: `firstValue`")
- var first: Promise {
- return firstValue
- }
-
- @available(*, deprecated, message: "See: `lastValue`")
- var last: Promise {
- return lastValue
- }
-}
-
-public extension Thenable where T: Sequence, T.Iterator.Element: Comparable {
- @available(*, deprecated, message: "See: `sortedValues`")
- func sorted(on: DispatchQueue? = conf.Q.map) -> Promise<[T.Iterator.Element]> {
- return sortedValues(on: on)
- }
-}
diff --git a/Sources/Info.plist b/Sources/Info.plist
deleted file mode 100644
index 3a619de4d..000000000
--- a/Sources/Info.plist
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- $(CURRENT_PROJECT_VERSION)
- CFBundleSignature
- ????
- CFBundleVersion
- 1
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
-
-
-
diff --git a/Sources/LogEvent.swift b/Sources/LogEvent.swift
deleted file mode 100644
index 99683bdb6..000000000
--- a/Sources/LogEvent.swift
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- The PromiseKit events which may be logged.
-
- ````
- /// A promise or guarantee has blocked the main thread
- case waitOnMainThread
-
- /// A promise has been deallocated without being resolved
- case pendingPromiseDeallocated
-
- /// An error which occurred while fulfilling a promise was swallowed
- case cauterized(Error)
-
- /// Errors which give a string error message
- case misc (String)
- ````
-*/
-public enum LogEvent {
- /// A promise or guarantee has blocked the main thread
- case waitOnMainThread
-
- /// A promise has been deallocated without being resolved
- case pendingPromiseDeallocated
-
- /// A guarantee has been deallocated without being resolved
- case pendingGuaranteeDeallocated
-
- /// An error which occurred while resolving a promise was swallowed
- case cauterized(Error)
-}
diff --git a/Sources/NSMethodSignatureForBlock.m b/Sources/NSMethodSignatureForBlock.m
deleted file mode 100644
index 700c1b37e..000000000
--- a/Sources/NSMethodSignatureForBlock.m
+++ /dev/null
@@ -1,77 +0,0 @@
-#import
-
-struct PMKBlockLiteral {
- void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
- int flags;
- int reserved;
- void (*invoke)(void *, ...);
- struct block_descriptor {
- unsigned long int reserved; // NULL
- unsigned long int size; // sizeof(struct Block_literal_1)
- // optional helper functions
- void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
- void (*dispose_helper)(void *src); // IFF (1<<25)
- // required ABI.2010.3.16
- const char *signature; // IFF (1<<30)
- } *descriptor;
- // imported variables
-};
-
-typedef NS_OPTIONS(NSUInteger, PMKBlockDescriptionFlags) {
- PMKBlockDescriptionFlagsHasCopyDispose = (1 << 25),
- PMKBlockDescriptionFlagsHasCtor = (1 << 26), // helpers have C++ code
- PMKBlockDescriptionFlagsIsGlobal = (1 << 28),
- PMKBlockDescriptionFlagsHasStret = (1 << 29), // IFF BLOCK_HAS_SIGNATURE
- PMKBlockDescriptionFlagsHasSignature = (1 << 30)
-};
-
-// It appears 10.7 doesn't support quotes in method signatures. Remove them
-// via @rabovik's method. See https://github.com/OliverLetterer/SLObjectiveCRuntimeAdditions/pull/2
-#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8
-NS_INLINE static const char * pmk_removeQuotesFromMethodSignature(const char *str){
- char *result = malloc(strlen(str) + 1);
- BOOL skip = NO;
- char *to = result;
- char c;
- while ((c = *str++)) {
- if ('"' == c) {
- skip = !skip;
- continue;
- }
- if (skip) continue;
- *to++ = c;
- }
- *to = '\0';
- return result;
-}
-#endif
-
-static NSMethodSignature *NSMethodSignatureForBlock(id block) {
- if (!block)
- return nil;
-
- struct PMKBlockLiteral *blockRef = (__bridge struct PMKBlockLiteral *)block;
- PMKBlockDescriptionFlags flags = (PMKBlockDescriptionFlags)blockRef->flags;
-
- if (flags & PMKBlockDescriptionFlagsHasSignature) {
- void *signatureLocation = blockRef->descriptor;
- signatureLocation += sizeof(unsigned long int);
- signatureLocation += sizeof(unsigned long int);
-
- if (flags & PMKBlockDescriptionFlagsHasCopyDispose) {
- signatureLocation += sizeof(void(*)(void *dst, void *src));
- signatureLocation += sizeof(void (*)(void *src));
- }
-
- const char *signature = (*(const char **)signatureLocation);
-#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8
- signature = pmk_removeQuotesFromMethodSignature(signature);
- NSMethodSignature *nsSignature = [NSMethodSignature signatureWithObjCTypes:signature];
- free((void *)signature);
-
- return nsSignature;
-#endif
- return [NSMethodSignature signatureWithObjCTypes:signature];
- }
- return 0;
-}
diff --git a/Sources/PMKCallVariadicBlock.m b/Sources/PMKCallVariadicBlock.m
deleted file mode 100644
index 1453a7d26..000000000
--- a/Sources/PMKCallVariadicBlock.m
+++ /dev/null
@@ -1,120 +0,0 @@
-#import "NSMethodSignatureForBlock.m"
-#import
-#import
-#import "AnyPromise+Private.h"
-#import
-#import
-#import
-
-#ifndef PMKLog
-#define PMKLog NSLog
-#endif
-
-@interface PMKArray : NSObject {
-@public
- id objs[3];
- NSUInteger count;
-} @end
-
-@implementation PMKArray
-
-- (id)objectAtIndexedSubscript:(NSUInteger)idx {
- if (count <= idx) {
- // this check is necessary due to lack of checks in `pmk_safely_call_block`
- return nil;
- }
- return objs[idx];
-}
-
-@end
-
-id __PMKArrayWithCount(NSUInteger count, ...) {
- PMKArray *this = [PMKArray new];
- this->count = count;
- va_list args;
- va_start(args, count);
- for (NSUInteger x = 0; x < count; ++x)
- this->objs[x] = va_arg(args, id);
- va_end(args);
- return this;
-}
-
-
-static inline id _PMKCallVariadicBlock(id frock, id result) {
- NSCAssert(frock, @"");
-
- NSMethodSignature *sig = NSMethodSignatureForBlock(frock);
- const NSUInteger nargs = sig.numberOfArguments;
- const char rtype = sig.methodReturnType[0];
-
- #define call_block_with_rtype(type) ({^type{ \
- switch (nargs) { \
- case 1: \
- return ((type(^)(void))frock)(); \
- case 2: { \
- const id arg = [result class] == [PMKArray class] ? result[0] : result; \
- return ((type(^)(id))frock)(arg); \
- } \
- case 3: { \
- type (^block)(id, id) = frock; \
- return [result class] == [PMKArray class] \
- ? block(result[0], result[1]) \
- : block(result, nil); \
- } \
- case 4: { \
- type (^block)(id, id, id) = frock; \
- return [result class] == [PMKArray class] \
- ? block(result[0], result[1], result[2]) \
- : block(result, nil, nil); \
- } \
- default: \
- @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"PromiseKit: The provided block’s argument count is unsupported." userInfo:nil]; \
- }}();})
-
- switch (rtype) {
- case 'v':
- call_block_with_rtype(void);
- return nil;
- case '@':
- return call_block_with_rtype(id) ?: nil;
- case '*': {
- char *str = call_block_with_rtype(char *);
- return str ? @(str) : nil;
- }
- case 'c': return @(call_block_with_rtype(char));
- case 'i': return @(call_block_with_rtype(int));
- case 's': return @(call_block_with_rtype(short));
- case 'l': return @(call_block_with_rtype(long));
- case 'q': return @(call_block_with_rtype(long long));
- case 'C': return @(call_block_with_rtype(unsigned char));
- case 'I': return @(call_block_with_rtype(unsigned int));
- case 'S': return @(call_block_with_rtype(unsigned short));
- case 'L': return @(call_block_with_rtype(unsigned long));
- case 'Q': return @(call_block_with_rtype(unsigned long long));
- case 'f': return @(call_block_with_rtype(float));
- case 'd': return @(call_block_with_rtype(double));
- case 'B': return @(call_block_with_rtype(_Bool));
- case '^':
- if (strcmp(sig.methodReturnType, "^v") == 0) {
- call_block_with_rtype(void);
- return nil;
- }
- // else fall through!
- default:
- @throw [NSException exceptionWithName:@"PromiseKit" reason:@"PromiseKit: Unsupported method signature." userInfo:nil];
- }
-}
-
-static id PMKCallVariadicBlock(id frock, id result) {
- @try {
- return _PMKCallVariadicBlock(frock, result);
- } @catch (id thrown) {
- if ([thrown isKindOfClass:[NSString class]])
- return thrown;
- if ([thrown isKindOfClass:[NSError class]])
- return thrown;
-
- // we don’t catch objc exceptions: they are meant to crash your app
- @throw thrown;
- }
-}
diff --git a/Sources/PMKCloudKit/CKContainer+Promise.swift b/Sources/PMKCloudKit/CKContainer+Promise.swift
new file mode 100644
index 000000000..00ec575eb
--- /dev/null
+++ b/Sources/PMKCloudKit/CKContainer+Promise.swift
@@ -0,0 +1,66 @@
+#if canImport(CloudKit)
+
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import CloudKit
+
+/**
+ To import the `CKContainer` category:
+
+ use_frameworks!
+ pod "PromiseKit/CloudKit"
+
+ And then in your sources:
+
+ @import PromiseKit;
+*/
+public extension CKContainer {
+ /// Reports whether the current user’s iCloud account can be accessed.
+ func accountStatus() -> Promise {
+ return Promise { accountStatus(completionHandler: $0.resolve) }
+ }
+
+ /// Requests the specified permission from the user asynchronously.
+#if swift(<5.5)
+ func requestApplicationPermission(_ applicationPermissions: CKContainer_Application_Permissions) -> Promise {
+ return Promise { requestApplicationPermission(applicationPermissions, completionHandler: $0.resolve) }
+ }
+#else
+ func requestApplicationPermission(_ applicationPermissions: CKContainer.ApplicationPermissions) -> Promise {
+ return Promise { requestApplicationPermission(applicationPermissions, completionHandler: $0.resolve) }
+ }
+#endif
+
+ /// Checks the status of the specified permission asynchronously.
+#if swift(<5.5)
+ func status(forApplicationPermission applicationPermissions: CKContainer_Application_Permissions) -> Promise {
+ return Promise { status(forApplicationPermission: applicationPermissions, completionHandler: $0.resolve) }
+ }
+#else
+ func status(forApplicationPermission applicationPermissions: CKContainer.ApplicationPermissions) -> Promise {
+ return Promise { status(forApplicationPermission: applicationPermissions, completionHandler: $0.resolve) }
+ }
+#endif
+ /// Retrieves information about a single user based on the ID of the corresponding user record.
+ @available(macOS 10.12, iOS 10, tvOS 10, *)
+ func discoverUserIdentity(withUserRecordID recordID: CKRecord.ID) -> Promise {
+ return Promise { discoverUserIdentity(withUserRecordID: recordID, completionHandler: $0.resolve) }
+ }
+
+ /// Returns the user record ID associated with the current user.
+ func fetchUserRecordID() -> Promise {
+ return Promise { fetchUserRecordID(completionHandler: $0.resolve) }
+ }
+}
+
+#if !os(tvOS)
+@available(macOS 10.12, iOS 10, tvOS 10, *)
+public extension CKContainer {
+ func discoverAllIdentities() -> Promise<[CKUserIdentity]> {
+ return Promise { discoverAllIdentities(completionHandler: $0.resolve) }
+ }
+}
+#endif
+
+#endif
diff --git a/Sources/PMKCloudKit/CKDatabase+Promise.swift b/Sources/PMKCloudKit/CKDatabase+Promise.swift
new file mode 100644
index 000000000..df667efbe
--- /dev/null
+++ b/Sources/PMKCloudKit/CKDatabase+Promise.swift
@@ -0,0 +1,91 @@
+#if canImport(CloudKit)
+
+import CloudKit.CKDatabase
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+
+/**
+ To import the `CKDatabase` category:
+
+ use_frameworks!
+ pod "PromiseKit/CloudKit"
+
+ And then in your sources:
+
+ @import PromiseKit;
+*/
+public extension CKDatabase {
+ /// Fetches one record asynchronously from the current database.
+ func fetch(withRecordID recordID: CKRecord.ID) -> Promise {
+ return Promise { fetch(withRecordID: recordID, completionHandler: $0.resolve) }
+ }
+
+ /// Fetches one record zone asynchronously from the current database.
+ func fetch(withRecordZoneID recordZoneID: CKRecordZone.ID) -> Promise {
+ return Promise { fetch(withRecordZoneID: recordZoneID, completionHandler: $0.resolve) }
+ }
+ /// Fetches all record zones asynchronously from the current database.
+ func fetchAllRecordZones() -> Promise<[CKRecordZone]> {
+ return Promise { fetchAllRecordZones(completionHandler: $0.resolve) }
+ }
+
+ /// Saves one record zone asynchronously to the current database.
+ func save(_ record: CKRecord) -> Promise {
+ return Promise { save(record, completionHandler: $0.resolve) }
+ }
+
+ /// Saves one record zone asynchronously to the current database.
+ func save(_ recordZone: CKRecordZone) -> Promise {
+ return Promise { save(recordZone, completionHandler: $0.resolve) }
+ }
+
+ /// Delete one subscription object asynchronously from the current database.
+ func delete(withRecordID recordID: CKRecord.ID) -> Promise {
+ return Promise { delete(withRecordID: recordID, completionHandler: $0.resolve) }
+ }
+
+ /// Delete one subscription object asynchronously from the current database.
+ func delete(withRecordZoneID zoneID: CKRecordZone.ID) -> Promise {
+ return Promise { delete(withRecordZoneID: zoneID, completionHandler: $0.resolve) }
+ }
+
+ /// Searches the specified zone asynchronously for records that match the query parameters.
+ func perform(_ query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil) -> Promise<[CKRecord]> {
+ return Promise { perform(query, inZoneWith: zoneID, completionHandler: $0.resolve) }
+ }
+
+ /// Fetches the record for the current user.
+ func fetchUserRecord(_ container: CKContainer = CKContainer.default()) -> Promise {
+ return container.fetchUserRecordID().then(on: nil) { uid in
+ return self.fetch(withRecordID: uid)
+ }
+ }
+}
+
+#if !os(watchOS)
+public extension CKDatabase {
+ /// Fetches one record zone asynchronously from the current database.
+ func fetch(withSubscriptionID subscriptionID: String) -> Promise {
+ return Promise { fetch(withSubscriptionID: subscriptionID, completionHandler: $0.resolve) }
+ }
+
+ /// Fetches all subscription objects asynchronously from the current database.
+ func fetchAllSubscriptions() -> Promise<[CKSubscription]> {
+ return Promise { fetchAllSubscriptions(completionHandler: $0.resolve) }
+ }
+
+ /// Saves one subscription object asynchronously to the current database.
+ func save(_ subscription: CKSubscription) -> Promise {
+ return Promise { save(subscription, completionHandler: $0.resolve) }
+ }
+
+ /// Delete one subscription object asynchronously from the current database.
+ func delete(withSubscriptionID subscriptionID: String) -> Promise {
+ return Promise { delete(withSubscriptionID: subscriptionID, completionHandler: $0.resolve) }
+ }
+}
+#endif
+
+#endif
diff --git a/Sources/PMKCoreLocation/.gitignore b/Sources/PMKCoreLocation/.gitignore
new file mode 100644
index 000000000..bec9c1741
--- /dev/null
+++ b/Sources/PMKCoreLocation/.gitignore
@@ -0,0 +1,5 @@
+*.xcodeproj/**/xcuserdata/
+*.xcscmblueprint
+/Carthage
+/.build
+.DS_Store
\ No newline at end of file
diff --git a/Sources/PMKCoreLocation/.travis.yml b/Sources/PMKCoreLocation/.travis.yml
new file mode 100644
index 000000000..95c076137
--- /dev/null
+++ b/Sources/PMKCoreLocation/.travis.yml
@@ -0,0 +1,78 @@
+osx_image: xcode10.2
+language: swift
+os: osx
+
+branches:
+ only:
+ - master
+stages:
+ - lint
+ - carthage
+ - test
+jobs:
+ include:
+ - &pod
+ stage: lint
+ osx_image: xcode8.3
+ env: SWIFT=3.1
+ before_install:
+ gem install cocoapods --prerelease --version 1.7.0.beta.3
+ install:
+ carthage bootstrap --no-build PromiseKit
+ script: |
+ cd Carthage/Checkouts/PromiseKit
+ mv .github/PromiseKit.podspec .
+ rm -rf Extensions/CoreLocation/Sources
+ cp -R ../../../Sources Extensions/CoreLocation
+ pod lib lint --subspec=PromiseKit/CoreLocation --fail-fast --swift-version=$SWIFT
+ - <<: *pod
+ osx_image: xcode9.2
+ env: SWIFT=3.2
+ - <<: *pod
+ osx_image: xcode9.4
+ env: SWIFT=3.3
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=3.4
+ - <<: *pod
+ osx_image: xcode9.2
+ env: SWIFT=4.0
+ - <<: *pod
+ osx_image: xcode9.4
+ env: SWIFT=4.1
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=4.2
+ - <<: *pod
+ osx_image: xcode10.2
+ env: SWIFT=5.0
+
+ - &carthage
+ stage: carthage
+ osx_image: xcode9.2
+ script: |
+ carthage bootstrap --cache-builds
+ sed -i '' "s/SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;/SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;/" *.xcodeproj/project.pbxproj
+ carthage build --no-skip-current
+ cache.directories:
+ - Carthage
+ - <<: *carthage
+ osx_image: xcode9.4
+ - <<: *carthage
+ osx_image: xcode10.1
+ - <<: *carthage
+ osx_image: xcode10.2
+
+ - &test
+ stage: test
+ xcode_scheme: PMKCoreLocation
+ xcode_project: PMKCoreLocation.xcodeproj
+ xcode_destination: platform=macOS
+ cache.directories:
+ - Carthage
+ before_install:
+ carthage bootstrap --cache-builds --no-use-binaries
+ - <<: *test
+ xcode_destination: 'platform=iOS Simulator,OS=12.2,name=iPhone SE'
+ - <<: *test
+ xcode_destination: 'platform=tvOS Simulator,OS=12.2,name=Apple TV'
diff --git a/Sources/PMKCoreLocation/CLGeocoder+Promise.swift b/Sources/PMKCoreLocation/CLGeocoder+Promise.swift
new file mode 100644
index 000000000..792a01ce4
--- /dev/null
+++ b/Sources/PMKCoreLocation/CLGeocoder+Promise.swift
@@ -0,0 +1,85 @@
+#if canImport(CoreLocation)
+
+import CoreLocation.CLGeocoder
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+#if os(iOS) || os(watchOS) || os(macOS)
+import class Contacts.CNPostalAddress
+#endif
+
+/**
+ To import the `CLGeocoder` category:
+
+ use_frameworks!
+ pod "PromiseKit/CoreLocation"
+
+ And then in your sources:
+
+ import PromiseKit
+*/
+extension CLGeocoder {
+ /// Submits a reverse-geocoding request for the specified location.
+ public func reverseGeocode(location: CLLocation) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ reverseGeocodeLocation(location, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Submits a forward-geocoding request using the specified address dictionary.
+ @available(iOS, deprecated: 11.0)
+ public func geocode(_ addressDictionary: [String: String]) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ geocodeAddressDictionary(addressDictionary, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Submits a forward-geocoding request using the specified address string.
+ public func geocode(_ addressString: String) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ geocodeAddressString(addressString, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Submits a forward-geocoding request using the specified address string within the specified region.
+ public func geocode(_ addressString: String, region: CLRegion?) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ geocodeAddressString(addressString, in: region, completionHandler: seal.resolve)
+ }
+ }
+
+#if !os(tvOS) && swift(>=3.2)
+ /// Submits a forward-geocoding request using the specified postal address.
+ @available(iOS 11.0, OSX 10.13, watchOS 4.0, *)
+ public func geocodePostalAddress(_ postalAddress: CNPostalAddress) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ geocodePostalAddress(postalAddress, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Submits a forward-geocoding requesting using the specified locale and postal address
+ @available(iOS 11.0, OSX 10.13, watchOS 4.0, *)
+ public func geocodePostalAddress(_ postalAddress: CNPostalAddress, preferredLocale locale: Locale?) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ geocodePostalAddress(postalAddress, preferredLocale: locale, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Submits a reverse-geocoding request for the specified location and a preferred locale.
+ @available(iOS 11.0, OSX 10.13, watchOS 4.0, *)
+ public func reverseGeocode(location: CLLocation, preferredLocale locale: Locale?) -> Promise<[CLPlacemark]> {
+ return Promise { seal in
+ reverseGeocodeLocation(location, preferredLocale: locale, completionHandler: seal.resolve)
+ }
+ }
+#endif
+}
+
+// TODO still not possible in Swift 3.2
+//extension CLError: CancellableError {
+// public var isCancelled: Bool {
+// return self == .geocodeCanceled
+// }
+//}
+
+#endif
diff --git a/Sources/PMKCoreLocation/CLLocationManager+Promise.swift b/Sources/PMKCoreLocation/CLLocationManager+Promise.swift
new file mode 100644
index 000000000..7944ef37d
--- /dev/null
+++ b/Sources/PMKCoreLocation/CLLocationManager+Promise.swift
@@ -0,0 +1,315 @@
+#if canImport(CoreLocation)
+
+import CoreLocation.CLLocationManager
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+/**
+ To import the `CLLocationManager` category:
+
+ use_frameworks!
+ pod "PromiseKit/CoreLocation"
+
+ And then in your sources:
+
+ import PromiseKit
+*/
+extension CLLocationManager {
+
+ /// The type of location permission we are asking for
+ public enum RequestAuthorizationType {
+ /// Determine the authorization from the application’s plist
+ case automatic
+ /// Request always-authorization
+ case always
+ /// Request when-in-use-authorization
+ case whenInUse
+ }
+
+ public enum PMKError: Error {
+ case notAuthorized
+ case unhandledEnumCase
+ }
+
+ /**
+ Request the current location.
+ - Note: to obtain a single location use `Promise.lastValue`
+ - Parameters:
+ - authorizationType: requestAuthorizationType: We read your Info plist and try to
+ determine the authorization type we should request automatically. If you
+ want to force one or the other, change this parameter from its default
+ value.
+ - block: A block by which to perform any filtering of the locations that are
+ returned. In order to only retrieve accurate locations, only return true if the
+ locations horizontal accuracy < 50
+ - Returns: A new promise that fulfills with the most recent CLLocation that satisfies
+ the provided block if it exists. If the block does not exist, simply return the
+ last location.
+ */
+ public class func requestLocation(authorizationType: RequestAuthorizationType = .automatic, satisfying block: ((CLLocation) -> Bool)? = nil) -> Promise<[CLLocation]> {
+
+ func std() -> Promise<[CLLocation]> {
+ return LocationManager(satisfying: block).promise
+ }
+
+ func auth() -> Promise {
+ #if os(macOS)
+ return Promise()
+ #else
+ func auth(type: PMKCLAuthorizationType) -> Promise {
+ return AuthorizationCatcher(type: type).promise.done(on: nil) {
+ switch $0 {
+ case .restricted, .denied:
+ throw PMKError.notAuthorized
+ default:
+ break
+ }
+ }
+ }
+
+ switch authorizationType {
+ case .automatic:
+ switch Bundle.main.permissionType {
+ case .always, .both:
+ return auth(type: .always)
+ case .whenInUse:
+ return auth(type: .whenInUse)
+ }
+ case .whenInUse:
+ return auth(type: .whenInUse)
+ case .always:
+ return auth(type: .always)
+ }
+ #endif
+ }
+
+ switch CLLocationManager.authorizationStatus() {
+ case .authorizedAlways, .authorizedWhenInUse:
+ return std()
+ case .notDetermined:
+ return auth().then(std)
+ case .denied, .restricted:
+ return Promise(error: PMKError.notAuthorized)
+ @unknown default:
+ return Promise(error: PMKError.unhandledEnumCase)
+ }
+ }
+
+ @available(*, deprecated, renamed: "requestLocation")
+ public class func promise(_ requestAuthorizationType: RequestAuthorizationType = .automatic, satisfying block: ((CLLocation) -> Bool)? = nil) -> Promise<[CLLocation]> {
+ return requestLocation(authorizationType: requestAuthorizationType, satisfying: block)
+ }
+}
+
+private class LocationManager: CLLocationManager, CLLocationManagerDelegate {
+ let (promise, seal) = Promise<[CLLocation]>.pending()
+ let satisfyingBlock: ((CLLocation) -> Bool)?
+
+ @objc fileprivate func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
+ if let block = satisfyingBlock {
+ let satisfiedLocations = locations.filter(block)
+ if !satisfiedLocations.isEmpty {
+ seal.fulfill(satisfiedLocations)
+ } else {
+ #if os(tvOS)
+ requestLocation()
+ #endif
+ }
+ } else {
+ seal.fulfill(locations)
+ }
+ }
+
+ init(satisfying block: ((CLLocation) -> Bool)? = nil) {
+ satisfyingBlock = block
+ super.init()
+ delegate = self
+ #if !os(tvOS)
+ startUpdatingLocation()
+ #else
+ requestLocation()
+ #endif
+ _ = self.promise.ensure {
+ self.stopUpdatingLocation()
+ }
+ }
+
+ @objc func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
+ let (domain, code) = { ($0.domain, $0.code) }(error as NSError)
+ if code == CLError.locationUnknown.rawValue && domain == kCLErrorDomain {
+ // Apple docs say you should just ignore this error
+ print("PromiseKit: warning: CLError.locationUnknown")
+ } else {
+ seal.reject(error)
+ }
+ }
+}
+
+
+#if !os(macOS)
+
+extension CLLocationManager {
+ /**
+ Request CoreLocation authorization from the user
+ - Note: By default we try to determine the authorization type you want by inspecting your Info.plist
+ - Note: This method will not perform upgrades from “when-in-use” to “always” unless you specify `.always` for the value of `type`.
+ */
+ @available(iOS 8, tvOS 9, watchOS 2, *)
+ public class func requestAuthorization(type requestedAuthorizationType: RequestAuthorizationType = .automatic) -> Guarantee {
+
+ let currentStatus = CLLocationManager.authorizationStatus()
+
+ func std(type: PMKCLAuthorizationType) -> Guarantee {
+ if currentStatus == .notDetermined {
+ return AuthorizationCatcher(type: type).promise
+ } else {
+ return .value(currentStatus)
+ }
+ }
+
+ switch requestedAuthorizationType {
+ case .always:
+ func iOS11Check() -> Guarantee {
+ switch currentStatus {
+ case .notDetermined, .authorizedWhenInUse:
+ return AuthorizationCatcher(type: .always).promise
+ default:
+ return .value(currentStatus)
+ }
+ }
+ #if PMKiOS11
+ // ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
+ // otherwise the warning you get below cannot be removed
+ return iOS11Check()
+ #else
+ if #available(iOS 11, *) {
+ return iOS11Check()
+ } else {
+ return std(type: .always)
+ }
+ #endif
+
+ case .whenInUse:
+ return std(type: .whenInUse)
+
+ case .automatic:
+ if currentStatus == .notDetermined {
+ switch Bundle.main.permissionType {
+ case .both, .whenInUse:
+ return AuthorizationCatcher(type: .whenInUse).promise
+ case .always:
+ return AuthorizationCatcher(type: .always).promise
+ }
+ } else {
+ return .value(currentStatus)
+ }
+ }
+ }
+}
+
+@available(iOS 8, *)
+private class AuthorizationCatcher: CLLocationManager, CLLocationManagerDelegate {
+ let (promise, fulfill) = Guarantee.pending()
+ var retainCycle: AuthorizationCatcher?
+ let initialAuthorizationState = CLLocationManager.authorizationStatus()
+
+ init(type: PMKCLAuthorizationType) {
+ super.init()
+
+ func ask(type: PMKCLAuthorizationType) {
+ delegate = self
+ retainCycle = self
+
+ switch type {
+ case .always:
+ #if os(tvOS)
+ fallthrough
+ #else
+ requestAlwaysAuthorization()
+ #endif
+ case .whenInUse:
+ requestWhenInUseAuthorization()
+ }
+
+ promise.done { _ in
+ self.retainCycle = nil
+ }
+ }
+
+ func iOS11Check() {
+ switch (initialAuthorizationState, type) {
+ case (.notDetermined, .always), (.authorizedWhenInUse, .always), (.notDetermined, .whenInUse):
+ ask(type: type)
+ default:
+ fulfill(initialAuthorizationState)
+ }
+ }
+
+ #if PMKiOS11
+ // ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
+ // otherwise the warning you get below cannot be removed
+ iOS11Check()
+ #else
+ if #available(iOS 11, *) {
+ iOS11Check()
+ } else {
+ if initialAuthorizationState == .notDetermined {
+ ask(type: type)
+ } else {
+ fulfill(initialAuthorizationState)
+ }
+ }
+ #endif
+ }
+
+ @objc fileprivate func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
+ // `didChange` is a lie; it fires this immediately with the current status.
+ if status != initialAuthorizationState {
+ fulfill(status)
+ }
+ }
+}
+
+#endif
+
+private extension Bundle {
+ enum PermissionType {
+ case both
+ case always
+ case whenInUse
+ }
+
+ var permissionType: PermissionType {
+ func hasInfoPlistKey(_ key: String) -> Bool {
+ let value = object(forInfoDictionaryKey: key) as? String ?? ""
+ return !value.isEmpty
+ }
+
+ if hasInfoPlistKey("NSLocationAlwaysAndWhenInUseUsageDescription") {
+ return .both
+ }
+ if hasInfoPlistKey("NSLocationAlwaysUsageDescription") {
+ return .always
+ }
+ if hasInfoPlistKey("NSLocationWhenInUseUsageDescription") {
+ return .whenInUse
+ }
+
+ if #available(iOS 11, *) {
+ NSLog("PromiseKit: warning: `NSLocationAlwaysAndWhenInUseUsageDescription` key not set")
+ } else {
+ NSLog("PromiseKit: warning: `NSLocationWhenInUseUsageDescription` key not set")
+ }
+
+ // won't work, but we warned the user above at least
+ return .whenInUse
+ }
+}
+
+private enum PMKCLAuthorizationType {
+ case always
+ case whenInUse
+}
+
+#endif
diff --git a/Sources/PMKFoundation/NSNotificationCenter+Promise.swift b/Sources/PMKFoundation/NSNotificationCenter+Promise.swift
new file mode 100644
index 000000000..3b7f84345
--- /dev/null
+++ b/Sources/PMKFoundation/NSNotificationCenter+Promise.swift
@@ -0,0 +1,33 @@
+import Foundation
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+/**
+ To import the `NSNotificationCenter` category:
+
+ use_frameworks!
+ pod "PromiseKit/Foundation"
+
+ Or `NSNotificationCenter` is one of the categories imported by the umbrella pod:
+
+ use_frameworks!
+ pod "PromiseKit"
+
+ And then in your sources:
+
+ import PromiseKit
+*/
+extension NotificationCenter {
+ /// Observe the named notification once
+ public func observe(once name: Notification.Name, object: Any? = nil) -> Guarantee {
+ let (promise, fulfill) = Guarantee.pending()
+ #if os(Linux) && ((swift(>=4.0) && !swift(>=4.0.1)) || (swift(>=3.0) && !swift(>=3.2.1)))
+ let id = addObserver(forName: name, object: object, queue: nil, usingBlock: fulfill)
+ #else
+ let id = addObserver(forName: name, object: object, queue: nil, using: fulfill)
+ #endif
+ promise.done { _ in self.removeObserver(id) }
+ return promise
+ }
+}
diff --git a/Sources/PMKFoundation/NSObject+Promise.swift b/Sources/PMKFoundation/NSObject+Promise.swift
new file mode 100644
index 000000000..c40bc8cb0
--- /dev/null
+++ b/Sources/PMKFoundation/NSObject+Promise.swift
@@ -0,0 +1,61 @@
+#if !os(Linux) && !os(Windows)
+
+import Foundation
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+/**
+ To import the `NSObject` category:
+
+ use_frameworks!
+ pod "PromiseKit/Foundation"
+
+ Or `NSObject` is one of the categories imported by the umbrella pod:
+
+ use_frameworks!
+ pod "PromiseKit"
+
+ And then in your sources:
+
+ import PromiseKit
+*/
+extension NSObject {
+ /**
+ - Returns: A promise that resolves when the provided keyPath changes.
+ - Warning: *Important* The promise must not outlive the object under observation.
+ - SeeAlso: Apple’s KVO documentation.
+ */
+ public func observe(_: PMKNamespacer, keyPath: String) -> Guarantee {
+ return Guarantee { KVOProxy(observee: self, keyPath: keyPath, resolve: $0) }
+ }
+}
+
+private class KVOProxy: NSObject {
+ var retainCycle: KVOProxy?
+ let fulfill: (Any?) -> Void
+
+ @discardableResult
+ init(observee: NSObject, keyPath: String, resolve: @escaping (Any?) -> Void) {
+ fulfill = resolve
+ super.init()
+ observee.addObserver(self, forKeyPath: keyPath, options: NSKeyValueObservingOptions.new, context: pointer)
+ retainCycle = self
+ }
+
+ fileprivate override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
+ if let change = change, context == pointer {
+ defer { retainCycle = nil }
+ fulfill(change[NSKeyValueChangeKey.newKey])
+ if let object = object as? NSObject, let keyPath = keyPath {
+ object.removeObserver(self, forKeyPath: keyPath)
+ }
+ }
+ }
+
+ private lazy var pointer: UnsafeMutableRawPointer = {
+ return Unmanaged.passUnretained(self).toOpaque()
+ }()
+}
+
+#endif
diff --git a/Sources/PMKFoundation/NSURLSession+Promise.swift b/Sources/PMKFoundation/NSURLSession+Promise.swift
new file mode 100644
index 000000000..deb913b48
--- /dev/null
+++ b/Sources/PMKFoundation/NSURLSession+Promise.swift
@@ -0,0 +1,240 @@
+import Foundation
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+#if canImport(FoundationNetworking)
+import FoundationNetworking
+#endif
+
+/**
+ To import the `NSURLSession` category:
+
+ use_frameworks!
+ pod "PromiseKit/Foundation"
+
+ Or `NSURLSession` is one of the categories imported by the umbrella pod:
+
+ use_frameworks!
+ pod "PromiseKit"
+
+ And then in your sources:
+
+ import PromiseKit
+*/
+extension URLSession {
+ /**
+ Example usage:
+
+ firstly {
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.compactMap { data, _ in
+ try JSONSerialization.jsonObject(with: data) as? [String: Any]
+ }.then { json in
+ //…
+ }
+
+ We recommend the use of [OMGHTTPURLRQ] which allows you to construct correct REST requests:
+
+ firstly {
+ let rq = OMGHTTPURLRQ.POST(url, json: parameters)
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.then { data, urlResponse in
+ //…
+ }
+
+ We provide a convenience initializer for `String` specifically for this promise:
+
+ firstly {
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.compactMap(String.init).then { string in
+ // decoded per the string encoding specified by the server
+ }.then { string in
+ print("response: string")
+ }
+
+ Other common types can be easily decoded using compactMap also:
+
+ firstly {
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.compactMap {
+ UIImage(data: $0)
+ }.then {
+ self.imageView.image = $0
+ }
+
+ Though if you do decode the image this way, we recommend inflating it on a background thread
+ first as this will improve main thread performance when rendering the image:
+
+ firstly {
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.compactMap(on: QoS.userInitiated) { data, _ in
+ guard let img = UIImage(data: data) else { return nil }
+ _ = cgImage?.dataProvider?.data
+ return img
+ }.then {
+ self.imageView.image = $0
+ }
+
+ - Parameter convertible: A URL or URLRequest.
+ - Returns: A promise that represents the URL request.
+ - SeeAlso: [OMGHTTPURLRQ]
+ - Remark: We deliberately don’t provide a `URLRequestConvertible` for `String` because in our experience, you should be explicit with this error path to make good apps.
+
+ [OMGHTTPURLRQ]: https://github.com/mxcl/OMGHTTPURLRQ
+ */
+ public func dataTask(_: PMKNamespacer, with convertible: URLRequestConvertible) -> Promise<(data: Data, response: URLResponse)> {
+ return Promise { dataTask(with: convertible.pmkRequest, completionHandler: adapter($0)).resume() }
+ }
+
+ public func uploadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, from data: Data) -> Promise<(data: Data, response: URLResponse)> {
+ return Promise { uploadTask(with: convertible.pmkRequest, from: data, completionHandler: adapter($0)).resume() }
+ }
+
+ public func uploadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, fromFile file: URL) -> Promise<(data: Data, response: URLResponse)> {
+ return Promise { uploadTask(with: convertible.pmkRequest, fromFile: file, completionHandler: adapter($0)).resume() }
+ }
+
+ /// - Remark: we force a `to` parameter because Apple deletes the downloaded file immediately after the underyling completion handler returns.
+ /// - Note: we do not create the destination directory for you, because we move the file with FileManager.moveItem which changes it behavior depending on the directory status of the URL you provide. So create your own directory first!
+ public func downloadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, to saveLocation: URL) -> Promise<(saveLocation: URL, response: URLResponse)> {
+ return Promise { seal in
+ downloadTask(with: convertible.pmkRequest, completionHandler: { tmp, rsp, err in
+ if let error = err {
+ seal.reject(error)
+ } else if let rsp = rsp, let tmp = tmp {
+ do {
+ try FileManager.default.moveItem(at: tmp, to: saveLocation)
+ seal.fulfill((saveLocation, rsp))
+ } catch {
+ seal.reject(error)
+ }
+ } else {
+ seal.reject(PMKError.invalidCallingConvention)
+ }
+ }).resume()
+ }
+ }
+}
+
+
+public protocol URLRequestConvertible {
+ var pmkRequest: URLRequest { get }
+}
+extension URLRequest: URLRequestConvertible {
+ public var pmkRequest: URLRequest { return self }
+}
+extension URL: URLRequestConvertible {
+ public var pmkRequest: URLRequest { return URLRequest(url: self) }
+}
+
+
+#if !os(Linux) && !os(Windows)
+public extension String {
+ /**
+ - Remark: useful when converting a `URLSession` response into a `String`
+
+ firstly {
+ URLSession.shared.dataTask(.promise, with: rq)
+ }.map(String.init).done {
+ print($0)
+ }
+ */
+ init?(data: Data, urlResponse: URLResponse) {
+ guard let str = String(bytes: data, encoding: urlResponse.stringEncoding ?? .utf8) else {
+ return nil
+ }
+ self.init(str)
+ }
+}
+
+private extension URLResponse {
+ var stringEncoding: String.Encoding? {
+ guard let encodingName = textEncodingName else { return nil }
+ let encoding = CFStringConvertIANACharSetNameToEncoding(encodingName as CFString)
+ guard encoding != kCFStringEncodingInvalidId else { return nil }
+ return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(encoding))
+ }
+}
+#endif
+
+private func adapter(_ seal: Resolver<(data: T, response: U)>) -> (T?, U?, Error?) -> Void {
+ return { t, u, e in
+ if let t = t, let u = u {
+ seal.fulfill((t, u))
+ } else if let e = e {
+ seal.reject(e)
+ } else {
+ seal.reject(PMKError.invalidCallingConvention)
+ }
+ }
+}
+
+
+public enum PMKHTTPError: Error, LocalizedError, CustomStringConvertible {
+ case badStatusCode(Int, Data, HTTPURLResponse)
+
+ public var errorDescription: String? {
+ func url(_ rsp: URLResponse) -> String {
+ return rsp.url?.absoluteString ?? "nil"
+ }
+ switch self {
+ case .badStatusCode(401, _, let response):
+ return "Unauthorized (\(url(response))"
+ case .badStatusCode(let code, _, let response):
+ return "Invalid HTTP response (\(code)) for \(url(response))."
+ }
+ }
+
+ public func decodeResponse(_ t: T.Type, decoder: JSONDecoder = JSONDecoder()) -> T? {
+ switch self {
+ case .badStatusCode(_, let data, _):
+ return try? decoder.decode(t, from: data)
+ }
+ }
+
+ //TODO rename responseJSON
+ public var jsonDictionary: Any? {
+ switch self {
+ case .badStatusCode(_, let data, _):
+ return try? JSONSerialization.jsonObject(with: data)
+ }
+ }
+
+ var responseBodyString: String? {
+ switch self {
+ case .badStatusCode(_, let data, _):
+ return String(data: data, encoding: .utf8)
+ }
+ }
+
+ public var failureReason: String? {
+ return responseBodyString
+ }
+
+ public var description: String {
+ switch self {
+ case .badStatusCode(let code, let data, let response):
+ var dict: [String: Any] = [
+ "Status Code": code,
+ "Body": String(data: data, encoding: .utf8) ?? "\(data.count) bytes"
+ ]
+ dict["URL"] = response.url
+ dict["Headers"] = response.allHeaderFields
+ return " \(NSDictionary(dictionary: dict))" // as NSDictionary makes the output look like NSHTTPURLResponse looks
+ }
+ }
+}
+
+public extension Promise where T == (data: Data, response: URLResponse) {
+ func validate() -> Promise {
+ return map {
+ guard let response = $0.response as? HTTPURLResponse else { return $0 }
+ switch response.statusCode {
+ case 200..<300:
+ return $0
+ case let code:
+ throw PMKHTTPError.badStatusCode(code, $0.data, response)
+ }
+ }
+ }
+}
diff --git a/Sources/PMKFoundation/Process+Promise.swift b/Sources/PMKFoundation/Process+Promise.swift
new file mode 100644
index 000000000..a88cb159c
--- /dev/null
+++ b/Sources/PMKFoundation/Process+Promise.swift
@@ -0,0 +1,175 @@
+#if os(macOS)
+
+import Foundation
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+/**
+ To import the `Process` category:
+
+ use_frameworks!
+ pod "PromiseKit/Foundation"
+
+ Or `Process` is one of the categories imported by the umbrella pod:
+
+ use_frameworks!
+ pod "PromiseKit"
+
+ And then in your sources:
+
+ import PromiseKit
+ */
+extension Process {
+ /**
+ Launches the receiver and resolves when it exits.
+
+ let proc = Process()
+ proc.launchPath = "/bin/ls"
+ proc.arguments = ["/bin"]
+ proc.launch(.promise).compactMap { std in
+ String(data: std.out.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
+ }.then { stdout in
+ print(str)
+ }
+ */
+ public func launch(_: PMKNamespacer) -> Promise<(out: Pipe, err: Pipe)> {
+ let (stdout, stderr) = (Pipe(), Pipe())
+
+ do {
+ standardOutput = stdout
+ standardError = stderr
+
+ if #available(OSX 10.13, *) {
+ try run()
+ } else if let path = launchPath, FileManager.default.isExecutableFile(atPath: path) {
+ launch()
+ } else {
+ throw PMKError.notExecutable(launchPath)
+ }
+ } catch {
+ return Promise(error: error)
+ }
+
+
+ var q: DispatchQueue {
+ if #available(macOS 10.10, iOS 8.0, tvOS 9.0, watchOS 2.0, *) {
+ return DispatchQueue.global(qos: .default)
+ } else {
+ return DispatchQueue.global(priority: .default)
+ }
+ }
+
+ return Promise { seal in
+ q.async {
+ self.waitUntilExit()
+
+ guard self.terminationReason == .exit, self.terminationStatus == 0 else {
+ let stdoutData = try? self.readDataFromPipe(stdout)
+ let stderrData = try? self.readDataFromPipe(stderr)
+
+ let stdoutString = stdoutData.flatMap { (data: Data) -> String? in String(data: data, encoding: .utf8) }
+ let stderrString = stderrData.flatMap { (data: Data) -> String? in String(data: data, encoding: .utf8) }
+
+ return seal.reject(PMKError.execution(process: self, standardOutput: stdoutString, standardError: stderrString))
+ }
+ seal.fulfill((stdout, stderr))
+ }
+ }
+ }
+
+ private func readDataFromPipe(_ pipe: Pipe) throws -> Data {
+ let handle = pipe.fileHandleForReading
+ defer { handle.closeFile() }
+
+ // Someday, NSFileHandle will probably be updated with throwing equivalents to its read and write methods,
+ // as NSTask has, to avoid raising exceptions and crashing the app.
+ // Unfortunately that day has not yet come, so use the underlying BSD calls for now.
+
+ let fd = handle.fileDescriptor
+
+ let bufsize = 1024 * 8
+ let buf = UnsafeMutablePointer.allocate(capacity: bufsize)
+
+ defer { buf.deallocate() }
+
+ var data = Data()
+
+ while true {
+ let bytesRead = read(fd, buf, bufsize)
+
+ if bytesRead == 0 {
+ break
+ }
+
+ if bytesRead < 0 {
+ throw POSIXError.Code(rawValue: errno).map { POSIXError($0) } ?? CocoaError(.fileReadUnknown)
+ }
+
+ data.append(buf, count: bytesRead)
+ }
+
+ return data
+ }
+
+ /**
+ The error generated by PromiseKit’s `Process` extension
+ */
+ public enum PMKError {
+ /// NOT AVAILABLE ON 10.13 and above because Apple provide this error handling themselves
+ case notExecutable(String?)
+ case execution(process: Process, standardOutput: String?, standardError: String?)
+ }
+}
+
+
+extension Process.PMKError: LocalizedError {
+ public var errorDescription: String? {
+ switch self {
+ case .notExecutable(let path?):
+ return "File not executable: \(path)"
+ case .notExecutable(nil):
+ return "No launch path specified"
+ case .execution(process: let task, standardOutput: _, standardError: _):
+ return "Failed executing: `\(task)` (\(task.terminationStatus))."
+ }
+ }
+}
+
+public extension Promise where T == (out: Pipe, err: Pipe) {
+ func print() -> Promise {
+ return tap { result in
+ switch result {
+ case .success(let raw):
+ let stdout = String(data: raw.out.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
+ let stderr = String(data: raw.err.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
+ Swift.print("stdout: `\(stdout ?? "")`")
+ Swift.print("stderr: `\(stderr ?? "")`")
+ case .failure(let err):
+ Swift.print(err)
+ }
+ }
+ }
+}
+
+extension Process {
+ /// Provided because Foundation’s is USELESS
+ open override var description: String {
+ let launchPath = self.launchPath ?? "$0"
+ var args = [launchPath]
+ arguments.flatMap{ args += $0 }
+ return args.map { arg in
+ let contains: Bool
+ contains = arg.contains(" ")
+ if contains {
+ return "\"\(arg)\""
+ } else if arg == "" {
+ return "\"\""
+ } else {
+ return arg
+ }
+ }.joined(separator: " ")
+ }
+}
+
+#endif
diff --git a/Sources/PMKFoundation/afterlife.swift b/Sources/PMKFoundation/afterlife.swift
new file mode 100644
index 000000000..b7168d921
--- /dev/null
+++ b/Sources/PMKFoundation/afterlife.swift
@@ -0,0 +1,30 @@
+#if !os(Linux) && !os(Windows)
+
+import Foundation
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+
+/**
+ - Returns: A promise that resolves when the provided object deallocates
+ - Important: The promise is not guaranteed to resolve immediately when the provided object is deallocated. So you cannot write code that depends on exact timing.
+ */
+public func after(life object: NSObject) -> Guarantee {
+ var reaper = objc_getAssociatedObject(object, &handle) as? GrimReaper
+ if reaper == nil {
+ reaper = GrimReaper()
+ objc_setAssociatedObject(object, &handle, reaper, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+ }
+ return reaper!.promise
+}
+
+private var handle: UInt8 = 0
+
+private class GrimReaper: NSObject {
+ deinit {
+ fulfill(())
+ }
+ let (promise, fulfill) = Guarantee.pending()
+}
+
+#endif
diff --git a/Sources/PMKHealthKit/.gitignore b/Sources/PMKHealthKit/.gitignore
new file mode 100644
index 000000000..bec9c1741
--- /dev/null
+++ b/Sources/PMKHealthKit/.gitignore
@@ -0,0 +1,5 @@
+*.xcodeproj/**/xcuserdata/
+*.xcscmblueprint
+/Carthage
+/.build
+.DS_Store
\ No newline at end of file
diff --git a/Sources/PMKHealthKit/.travis.yml b/Sources/PMKHealthKit/.travis.yml
new file mode 100644
index 000000000..91caf3a78
--- /dev/null
+++ b/Sources/PMKHealthKit/.travis.yml
@@ -0,0 +1,76 @@
+osx_image: xcode10.2
+language: swift
+os: osx
+
+branches:
+ only:
+ - master
+stages:
+ - lint
+ - test
+jobs:
+ include:
+ - &pod
+ stage: lint
+ osx_image: xcode8.3
+ env: SWIFT=3.1
+ cache: cocoapods
+ before_install:
+ gem install cocoapods --prerelease --version 1.7.0.beta.3
+ install:
+ carthage bootstrap --no-build PromiseKit
+ script: |
+ cd Carthage/Checkouts/PromiseKit
+ mv .github/PromiseKit.podspec .
+ rm -rf Extensions/HealthKit/Sources
+ cp -R ../../../Sources Extensions/HealthKit
+ pod lib lint --subspec=PromiseKit/HealthKit --fail-fast --swift-version=$SWIFT
+ - <<: *pod
+ osx_image: xcode9.2
+ env: SWIFT=3.2
+ - <<: *pod
+ osx_image: xcode9.4
+ env: SWIFT=3.3
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=3.4
+ - <<: *pod
+ osx_image: xcode9.2
+ env: SWIFT=4.0
+ - <<: *pod
+ osx_image: xcode9.4
+ env: SWIFT=4.1
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=4.2
+ - <<: *pod
+ osx_image: xcode10.2
+ env: SWIFT=4.3
+ - <<: *pod
+ osx_image: xcode10.2
+ env: SWIFT=5.0
+
+ - &carthage
+ stage: carthage
+ osx_image: xcode9.2
+ script: |
+ carthage bootstrap --cache-builds --platform iOS,macOS
+ sed -i '' "s/SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;/SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;/" *.xcodeproj/project.pbxproj
+ carthage build --no-skip-current
+ cache.directories:
+ - Carthage
+ - <<: *carthage
+ osx_image: xcode9.4
+ - <<: *carthage
+ osx_image: xcode10.1
+ - <<: *carthage
+ osx_image: xcode10.2
+
+ - stage: test
+ xcode_scheme: PMKHealthKit
+ xcode_project: PMKHealthKit.xcodeproj
+ xcode_destination: 'platform=iOS Simulator,OS=12.2,name=iPhone SE'
+ cache.directories:
+ - Carthage
+ before_install:
+ carthage bootstrap --cache-builds --no-use-binaries
diff --git a/Sources/PMKHealthKit/HealthKit+Promise.swift b/Sources/PMKHealthKit/HealthKit+Promise.swift
new file mode 100644
index 000000000..bc40f41c1
--- /dev/null
+++ b/Sources/PMKHealthKit/HealthKit+Promise.swift
@@ -0,0 +1,87 @@
+#if !os(tvOS) && canImport(HealthKit)
+
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HealthKit
+
+public extension HKHealthStore {
+ func requestAuthorization(toShare typesToShare: Set?, read typesToRead: Set?) -> Promise {
+ return Promise { seal in
+ requestAuthorization(toShare: typesToShare, read: typesToRead, completion: seal.resolve)
+ }
+ }
+
+#if os(iOS)
+ func enableBackgroundDelivery(for type: HKObjectType, frequency: HKUpdateFrequency) -> Promise {
+ return Promise { seal in
+ enableBackgroundDelivery(for: type, frequency: frequency, withCompletion: seal.resolve)
+ }
+ }
+#endif
+}
+
+public extension HKStatisticsQuery {
+ static func promise(quantityType: HKQuantityType, quantitySamplePredicate: NSPredicate? = nil, options: HKStatisticsOptions = [], healthStore: HKHealthStore = .init()) -> Promise {
+ return Promise { seal in
+ let query = HKStatisticsQuery(quantityType: quantityType, quantitySamplePredicate: quantitySamplePredicate, options: options) {
+ seal.resolve($1, $2)
+ }
+ healthStore.execute(query)
+ }
+ }
+}
+
+public extension HKAnchoredObjectQuery {
+ static func promise(type: HKSampleType, predicate: NSPredicate? = nil, anchor: HKQueryAnchor? = nil, limit: Int = HKObjectQueryNoLimit, healthStore: HKHealthStore = .init()) -> Promise<([HKSample], [HKDeletedObject], HKQueryAnchor)> {
+ return Promise { seal in
+ let query = HKAnchoredObjectQuery(type: type, predicate: predicate, anchor: anchor, limit: limit) {
+ if let a = $1, let b = $2, let c = $3 {
+ seal.fulfill((a, b, c))
+ } else if let e = $4 {
+ seal.reject(e)
+ } else {
+ seal.reject(PMKError.invalidCallingConvention)
+ }
+ }
+ healthStore.execute(query)
+ }
+ }
+
+}
+
+public extension HKStatisticsCollectionQuery {
+ func promise(healthStore: HKHealthStore = .init()) -> Promise {
+ return Promise { seal in
+ initialResultsHandler = {
+ seal.resolve($1, $2)
+ }
+ healthStore.execute(self)
+ }
+ }
+}
+
+public extension HKSampleQuery {
+ static func promise(sampleType: HKSampleType, predicate: NSPredicate? = nil, limit: Int = HKObjectQueryNoLimit, sortDescriptors: [NSSortDescriptor]? = nil, healthStore: HKHealthStore = .init()) -> Promise<[HKSample]> {
+ return Promise { seal in
+ let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: limit, sortDescriptors: sortDescriptors) {
+ seal.resolve($1, $2)
+ }
+ healthStore.execute(query)
+ }
+ }
+}
+
+@available(iOS 9.3, iOSApplicationExtension 9.3, watchOSApplicationExtension 2.2, *)
+public extension HKActivitySummaryQuery {
+ static func promise(predicate: NSPredicate, healthStore: HKHealthStore = .init()) -> Promise<[HKActivitySummary]> {
+ return Promise { seal in
+ let query = HKActivitySummaryQuery(predicate: predicate) {
+ seal.resolve($1, $2)
+ }
+ healthStore.execute(query)
+ }
+ }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/.gitignore b/Sources/PMKHomeKit/.gitignore
new file mode 100644
index 000000000..bec9c1741
--- /dev/null
+++ b/Sources/PMKHomeKit/.gitignore
@@ -0,0 +1,5 @@
+*.xcodeproj/**/xcuserdata/
+*.xcscmblueprint
+/Carthage
+/.build
+.DS_Store
\ No newline at end of file
diff --git a/Sources/PMKHomeKit/.travis.yml b/Sources/PMKHomeKit/.travis.yml
new file mode 100644
index 000000000..5a0f7450a
--- /dev/null
+++ b/Sources/PMKHomeKit/.travis.yml
@@ -0,0 +1,67 @@
+os: osx
+language: swift
+osx_image: xcode10.2
+
+branches:
+ only:
+ - master
+stages:
+ - lint
+ - carthage
+ - test
+jobs:
+ include:
+ - &pod
+ stage: lint
+ osx_image: xcode9.4
+ env: SWIFT=3.3
+ before_install:
+ gem install cocoapods --prerelease --version 1.7.0.beta.3
+ install:
+ carthage bootstrap --no-build PromiseKit
+ script: |
+ cd Carthage/Checkouts/PromiseKit
+ mv .github/PromiseKit.podspec .
+ rm -rf Extensions/HomeKit/Sources
+ cp -R ../../../Sources Extensions/HomeKit
+ pod lib lint --subspec=PromiseKit/HomeKit --fail-fast --swift-version=$SWIFT
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=3.4
+ - <<: *pod
+ osx_image: xcode9.4
+ env: SWIFT=4.1
+ - <<: *pod
+ osx_image: xcode10.1
+ env: SWIFT=4.2
+ - <<: *pod
+ osx_image: xcode10.2
+ env: SWIFT=5.0
+
+ - &carthage
+ stage: carthage
+ osx_image: xcode9.4
+ script: |
+ carthage bootstrap --cache-builds
+ sed -i '' "s/SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;/SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;/" *.xcodeproj/project.pbxproj
+ carthage build --no-skip-current
+ cache.directories:
+ - Carthage
+ - <<: *carthage
+ osx_image: xcode10.1
+ - <<: *carthage
+ osx_image: xcode10.2
+
+ - &test
+ stage: test
+ xcode_scheme: PMKHomeKit
+ xcode_project: PMKHomeKit.xcodeproj
+ xcode_destination: 'platform=iOS Simulator,OS=12.2,name=iPhone SE'
+ cache.directories:
+ - Carthage
+ before_install:
+ carthage bootstrap --cache-builds --no-use-binaries
+ after_success:
+ bash <(curl -s https://codecov.io/bash);
+ - <<: *test
+ xcode_destination: 'platform=tvOS Simulator,OS=12.2,name=Apple TV'
diff --git a/Sources/PMKHomeKit/HMAcessoryBrowser+Promise.swift b/Sources/PMKHomeKit/HMAcessoryBrowser+Promise.swift
new file mode 100644
index 000000000..7199d5be6
--- /dev/null
+++ b/Sources/PMKHomeKit/HMAcessoryBrowser+Promise.swift
@@ -0,0 +1,76 @@
+#if canImport(HomeKit) && !os(tvOS) && !os(watchOS)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+public enum HMPromiseAccessoryBrowserError: Error {
+ case noAccessoryFound
+}
+
+public class HMPromiseAccessoryBrowser {
+ private var proxy: BrowserProxy?
+
+ public func start(scanInterval: ScanInterval) -> Promise<[HMAccessory]> {
+ proxy = BrowserProxy(scanInterval: scanInterval)
+ return proxy!.promise
+ }
+
+ public func stop() {
+ proxy?.cancel()
+ }
+}
+
+private class BrowserProxy: PromiseProxy<[HMAccessory]>, HMAccessoryBrowserDelegate {
+ let browser = HMAccessoryBrowser()
+ let scanInterval: ScanInterval
+
+ init(scanInterval: ScanInterval) {
+ self.scanInterval = scanInterval
+ super.init()
+
+ browser.delegate = self;
+ browser.startSearchingForNewAccessories()
+
+ //if we have a timeout, set it up
+ var timeout: TimeInterval? = nil
+ switch scanInterval {
+ case .returnAll(let interval): timeout = interval
+ case .returnFirst(let interval): timeout = interval
+ }
+
+ if let timeout = timeout {
+ after(seconds: timeout)
+ .done { [weak self] () -> Void in
+ guard let _self = self else { return }
+ _self.reject(HMPromiseAccessoryBrowserError.noAccessoryFound)
+ }
+ }
+ }
+
+ override func fulfill(_ value: [HMAccessory]) {
+ browser.stopSearchingForNewAccessories()
+ super.fulfill(value)
+ }
+
+ override func reject(_ error: Error ) {
+ browser.stopSearchingForNewAccessories()
+ super.reject(error)
+ }
+
+ override func cancel() {
+ browser.stopSearchingForNewAccessories()
+ super.cancel()
+ }
+
+ /**
+ HMAccessoryBrowser delegate
+ */
+ func accessoryBrowser(_ browser: HMAccessoryBrowser, didFindNewAccessory accessory: HMAccessory) {
+ if case .returnFirst = scanInterval {
+ fulfill([accessory])
+ }
+ }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMActionSet+Promise.swift b/Sources/PMKHomeKit/HMActionSet+Promise.swift
new file mode 100644
index 000000000..ca14fed9a
--- /dev/null
+++ b/Sources/PMKHomeKit/HMActionSet+Promise.swift
@@ -0,0 +1,24 @@
+#if canImport(HomeKit) && !os(tvOS) && !os(watchOS)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+extension HMActionSet {
+
+ @available(iOS 8.0, *)
+ public func addAction(_ action: HMAction) -> Promise {
+ return Promise { seal in
+ self.addAction(action, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func updateName(_ name: String) -> Promise {
+ return Promise { seal in
+ self.updateName(name, completionHandler: seal.resolve)
+ }
+ }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMCharacteristic+Promise.swift b/Sources/PMKHomeKit/HMCharacteristic+Promise.swift
new file mode 100644
index 000000000..3649f8296
--- /dev/null
+++ b/Sources/PMKHomeKit/HMCharacteristic+Promise.swift
@@ -0,0 +1,48 @@
+#if canImport(HomeKit)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+public enum AccessoryError: Error {
+ case incorrectType
+ case serviceMissing
+ case characteristicMissing
+}
+
+@available(iOS 8.0, tvOS 10.0, *)
+extension HMCharacteristic {
+ /**
+ A simple typesafe promise wrapper around readValue
+ */
+ public func read() -> Promise {
+ return Promise { seal in
+ self.readValue { error in
+ if let error = error { seal.reject(error) }
+ else if let value = self.value as? T { seal.fulfill(value) }
+ else { seal.reject(AccessoryError.incorrectType) }
+ }
+ }
+ }
+ /// Because type inference is great... until you can't compile (thanks Swift)
+ public func readFloat() -> Promise { return read() }
+ public func readDouble() -> Promise { return read() }
+ public func readInt() -> Promise { return read() }
+ public func readString() -> Promise { return read() }
+
+ /**
+ A simple promise wrapper around writeValue
+ */
+ public func write(_ value: Any?) -> Promise {
+ return Promise { seal in
+ self.writeValue(value, completionHandler: seal.resolve)
+ }
+ }
+ /// Explicit is good
+ public func writeFloat(_ value: Float) -> Promise { return write(value) }
+ public func writeDouble(_ value: Double) -> Promise { return write(value) }
+ public func writeInt(_ value: Int) -> Promise { return write(value) }
+ public func writeString(_ value: String) -> Promise { return write(value) }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMEventTrigger+Promise.swift b/Sources/PMKHomeKit/HMEventTrigger+Promise.swift
new file mode 100644
index 000000000..fe6c79e9c
--- /dev/null
+++ b/Sources/PMKHomeKit/HMEventTrigger+Promise.swift
@@ -0,0 +1,19 @@
+#if canImport(HomeKit) && !os(tvOS) && !os(watchOS)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+@available(iOS 9.0, *)
+extension HMEventTrigger {
+
+ @available(iOS 11.0, *)
+ public func updateExecuteOnce(_ executeOnce: Bool) -> Promise {
+ return Promise { seal in
+ self.updateExecuteOnce(executeOnce, completionHandler: seal.resolve)
+ }
+ }
+
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMHome+Promise.swift b/Sources/PMKHomeKit/HMHome+Promise.swift
new file mode 100644
index 000000000..330f56c93
--- /dev/null
+++ b/Sources/PMKHomeKit/HMHome+Promise.swift
@@ -0,0 +1,114 @@
+#if canImport(HomeKit) && !os(tvOS) && !os(watchOS)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+extension HMHome {
+
+ @available(iOS 8.0, *)
+ public func updateName(_ name: String) -> Promise {
+ return Promise { seal in
+ self.updateName(name, completionHandler: seal.resolve)
+ }
+ }
+
+ // MARK: Accessories
+
+ /// Add and setup a new HMAccessory. Displays it's own UI
+ @available(iOS 11.3, *)
+ public func addAndSetupAccessories(with payload: HMAccessorySetupPayload) -> Promise<[HMAccessory]> {
+ return Promise { seal in
+ self.addAndSetupAccessories(with: payload, completionHandler: seal.resolve)
+ }
+ }
+
+ /// Add and setup a new HMAccessory. Displays it's own UI
+ @available(iOS 10.0, *)
+ public func addAndSetupAccessories() -> Promise<[HMAccessory]> {
+ // We need to compare what we have before the action to after to know what is new
+ let beforeAccessories = self.accessories
+ let home = self
+
+ return Promise { seal in
+ self.addAndSetupAccessories { error in
+ if let error = error { seal.reject(error) }
+ else {
+ let newAccessories = home.accessories.filter { beforeAccessories.contains($0) == false }
+ seal.fulfill(newAccessories)
+ }
+ }
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func addAccessory(_ accessory: HMAccessory) -> Promise {
+ return Promise { seal in
+ self.addAccessory(accessory, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func assignAccessory(_ accessory: HMAccessory, to room: HMRoom) -> Promise {
+ return Promise { seal in
+ self.assignAccessory(accessory, to: room, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func removeAccessory(_ accessory: HMAccessory) -> Promise {
+ return Promise { seal in
+ self.removeAccessory(accessory, completionHandler: seal.resolve)
+ }
+ }
+
+ // MARK: Rooms
+
+ @available(iOS 8.0, *)
+ public func addRoom(withName name: String) -> Promise {
+ return Promise { seal in
+ self.addRoom(withName: name, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func removeRoom(_ room: HMRoom) -> Promise {
+ return Promise { seal in
+ self.removeRoom(room, completionHandler: seal.resolve)
+ }
+ }
+
+ // MARK: Action Sets
+
+ @available(iOS 8.0, *)
+ public func addActionSet(withName name: String) -> Promise {
+ return Promise { seal in
+ self.addActionSet(withName: name, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func removeActionSet(_ actionSet: HMActionSet) -> Promise {
+ return Promise { seal in
+ self.removeActionSet(actionSet, completionHandler: seal.resolve)
+ }
+ }
+
+ // MARK: Triggers
+
+ @available(iOS 8.0, *)
+ public func addTrigger(_ trigger: HMTrigger) -> Promise {
+ return Promise { seal in
+ self.addTrigger(trigger, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func removeTrigger(_ trigger: HMTrigger) -> Promise {
+ return Promise { seal in
+ self.removeTrigger(trigger, completionHandler: seal.resolve)
+ }
+ }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMHomeManager+Promise.swift b/Sources/PMKHomeKit/HMHomeManager+Promise.swift
new file mode 100644
index 000000000..673a5795e
--- /dev/null
+++ b/Sources/PMKHomeKit/HMHomeManager+Promise.swift
@@ -0,0 +1,64 @@
+#if canImport(HomeKit)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+@available(iOS 8.0, tvOS 10.0, *)
+public enum HomeKitError: Error {
+ case permissionDeined
+}
+
+@available(iOS 8.0, tvOS 10.0, *)
+extension HMHomeManager {
+ public func homes() -> Promise<[HMHome]> {
+ return HMHomeManagerProxy().promise
+ }
+
+ #if !os(tvOS) && !os(watchOS)
+
+ @available(iOS 8.0, *)
+ public func addHome(withName name: String) -> Promise {
+ return Promise { seal in
+ self.addHome(withName: name, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func removeHome(_ home: HMHome) -> Promise {
+ return Promise { seal in
+ self.removeHome(home, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func updatePrimaryHome(_ home: HMHome) -> Promise {
+ return Promise { seal in
+ self.updatePrimaryHome(home, completionHandler: seal.resolve)
+ }
+ }
+
+ #endif
+}
+
+@available(iOS 8.0, tvOS 10.0, *)
+internal class HMHomeManagerProxy: PromiseProxy<[HMHome]>, HMHomeManagerDelegate {
+
+ fileprivate let manager: HMHomeManager
+
+ override init() {
+ self.manager = HMHomeManager()
+ super.init()
+ self.manager.delegate = self
+
+ DispatchQueue.main.asyncAfter(deadline: .now() + 20.0) { [weak self] in
+ self?.reject(HomeKitError.permissionDeined)
+ }
+ }
+
+ func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
+ fulfill(manager.homes)
+ }
+}
+
+#endif
diff --git a/Sources/PMKHomeKit/HMTrigger+Promise.swift b/Sources/PMKHomeKit/HMTrigger+Promise.swift
new file mode 100644
index 000000000..c56cef97b
--- /dev/null
+++ b/Sources/PMKHomeKit/HMTrigger+Promise.swift
@@ -0,0 +1,39 @@
+#if canImport(HomeKit) && !os(tvOS) && !os(watchOS)
+#if !PMKCocoaPods
+import PromiseKit
+#endif
+import HomeKit
+
+extension HMTrigger {
+
+ @available(iOS 8.0, *)
+ public func updateName(_ name: String) -> Promise {
+ return Promise { seal in
+ self.updateName(name, completionHandler: seal.resolve)
+ }
+ }
+
+ @available(iOS 8.0, *)
+ public func enable(_ enabled: Bool) -> Promise