├── Assets
├── logo.png
└── logo.sketch
├── Package.swift
├── docs.sh
├── .gitignore
├── Eventually.xcworkspace
└── contents.xcworkspacedata
├── Playground.playground
├── contents.xcplayground
└── Pages
│ ├── Errors.xcplaygroundpage
│ └── Contents.swift
│ ├── Execution Contexts.xcplaygroundpage
│ └── Contents.swift
│ └── Basics.xcplaygroundpage
│ └── Contents.swift
├── Sources
├── Observable.swift
├── Resolve.swift
├── FutureResult.swift
├── Mutex.swift
├── ExecutionContext.swift
├── Future+Operations.swift
└── Future.swift
├── Eventually.podspec
├── Configs
├── EventuallyTests.plist
└── Eventually.plist
├── LICENSE
├── Eventually.xcodeproj
├── xcshareddata
│ └── xcschemes
│ │ ├── Eventually-watchOS.xcscheme
│ │ ├── Eventually-tvOS.xcscheme
│ │ ├── Eventually-macOS.xcscheme
│ │ └── Eventually-iOS.xcscheme
└── project.pbxproj
├── README.md
└── Tests
└── EventuallyTests.swift
/Assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nrkno/Eventually/HEAD/Assets/logo.png
--------------------------------------------------------------------------------
/Assets/logo.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nrkno/Eventually/HEAD/Assets/logo.sketch
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | import PackageDescription
2 |
3 | let package = Package(
4 | name: "Eventually"
5 | )
6 |
--------------------------------------------------------------------------------
/docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | jazzy \
4 | --theme fullwidth \
5 | --author NRK \
6 | --author_url https://nrkno.github.io \
7 | --github_url https://github.com/nrkno/Eventually \
8 | --github-file-prefix https://github.com/nrkno/Eventually/tree/master
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # xcode noise
2 | build/*
3 | dist/*
4 | *.pbxuser
5 | *.mode1v3
6 | *.mode2v3
7 | *.perspectivev3
8 | *.moved-aside
9 |
10 | # osx noise
11 | .DS_Store
12 | profile
13 |
14 | *.xcodeproj/project.xcworkspace/*
15 | */xcuserdata/*
16 |
17 | docs/*
18 |
19 | *.playground/*.o
20 |
--------------------------------------------------------------------------------
/Eventually.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Playground.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Sources/Observable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Observable.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | internal final class Observable {
12 | let context: ExecutionContext
13 | private let observer: (FutureResult) -> Void
14 |
15 | init(context: ExecutionContext, observer: @escaping (FutureResult) -> Void) {
16 | self.context = context
17 | self.observer = observer
18 | }
19 |
20 | func call(result: FutureResult) {
21 | context.apply {
22 | self.observer(result)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Resolve.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Resolve.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 01/03/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Used to resolve a future, giving it either a success or a failure value.
12 | /// Note: mostly exist to give a slightly more fluid api when resolving a future
13 | public struct Resolve {
14 | internal let closure: ((FutureResult) -> Void)
15 |
16 | /// Resolves with a successful value
17 | public func success(_ value: T) {
18 | closure(.success(value))
19 | }
20 |
21 | // Resolves with an error
22 | public func failure(_ error: Error) {
23 | closure(.failure(error))
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Eventually.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "Eventually"
3 | s.version = "0.4"
4 | s.summary = "SWift Future/Promise library"
5 | s.description = <<-DESC
6 | A Swift Future/Promise library that can be used to model and transform asynchronous results
7 | DESC
8 | s.homepage = "https://github.com/nrkno/Eventually"
9 | s.license = { :type => "MIT", :file => "LICENSE" }
10 | s.author = { "Johan Sørensen" => "johan.sorensen@nrk.no" }
11 | s.ios.deployment_target = "9.0"
12 | s.osx.deployment_target = "10.10"
13 | s.watchos.deployment_target = "3.0"
14 | s.tvos.deployment_target = "9.0"
15 | s.source = { :git => "https://github.com/nrkno/Eventually.git", :tag => s.version.to_s }
16 | s.source_files = "Sources/**/*"
17 | s.frameworks = "Foundation"
18 | end
19 |
--------------------------------------------------------------------------------
/Configs/EventuallyTests.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Playground.playground/Pages/Errors.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Eventually
3 | import XCPlayground
4 | XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
5 |
6 | //: ## Error handling
7 |
8 | enum Trouble: Error {
9 | case fail
10 | }
11 |
12 | let failingFuture = Future { resolve in
13 | resolve.failure(Trouble.fail)
14 | }
15 |
16 | //: Switching on the Result type
17 |
18 | failingFuture.then { result in
19 | switch result {
20 | case .success(let value):
21 | print("failingFuture is", value)
22 | case .failure(let error):
23 | print("failingFuture failed: ", error)
24 | }
25 | }
26 |
27 | //: The success() + failure() helpers
28 |
29 | failingFuture.map { value in
30 | return "the value is \(value)"
31 | }.success { value in
32 | print(value)
33 | }.failure { error in
34 | print("Error: ", error)
35 | }
36 |
37 |
38 | //: [Previous: Basics](@previous) | [Previous: Execution Contexts](@next)
39 |
--------------------------------------------------------------------------------
/Configs/Eventually.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSHumanReadableCopyright
24 | Copyright © 2017 NRK. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Sources/FutureResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FutureResult.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Represents a Future result that can have only one of two states: .success (the value) or .failure (an error)
12 | public enum FutureResult {
13 | case success(T)
14 | case failure(Error)
15 |
16 | /// The value in case of .success
17 | public var value: T? {
18 | return map({ $0 })
19 | }
20 |
21 | /// The error in case of .failure
22 | public var error: Error? {
23 | if case .failure(let error) = self {
24 | return error
25 | }
26 | return nil
27 | }
28 |
29 | /// If self is .success then the transform closure is run on the result, otherwise nil is returned
30 | public func map(_ transform: (T) -> T) -> T? {
31 | switch self {
32 | case .success(let value):
33 | return transform(value)
34 | case .failure:
35 | return nil
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 NRK
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Playground.playground/Pages/Execution Contexts.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Eventually
3 | import XCPlayground
4 | XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
5 |
6 | /*:
7 | ## Execution Contexts
8 |
9 | Most of the methods takes an optional `on:` parameter that dictates on which ExecutionContext
10 | The task should be performed on, the ExecutionContext is a shorthand way of specifying the queue
11 | */
12 |
13 | //:First, create a Future that runs its resolve closure on a background queue
14 | let backgroundFuture = Future(on: .background) { resolve in
15 | // runs on background queue
16 | resolve.success(42)
17 | }
18 |
19 | //: Then we transform (map) the value of the future, once it has a value, on our own queue
20 | let queue = DispatchQueue(label: "no.nrk.Eventually.playground")
21 | let mapped = backgroundFuture.map(on: .queue(queue)) { value in
22 | // Runs on our own queue
23 | return value * Double.pi
24 | }
25 |
26 | //: Then we get notified on the main thread (the default) if the future resolves with a successful value
27 | mapped.success(on: .main) { value in
28 | print("back on main thread the value is", value)
29 | }
30 |
31 | //: [Previous: Errors](@previous)
32 |
--------------------------------------------------------------------------------
/Sources/Mutex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mutex.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | #if os(Linux)
10 | import Glibc
11 | #else
12 | import Darwin
13 | #endif
14 |
15 | internal final class Mutex {
16 | private var mutex = pthread_mutex_t()
17 |
18 | init(){
19 | let res = pthread_mutex_init(&mutex, nil)
20 | if res != 0 {
21 | fatalError("failed to init mutex: \(strerror(res))")
22 | }
23 | }
24 |
25 | deinit {
26 | let res = pthread_mutex_destroy(&mutex)
27 | if res != 0 {
28 | print("failed to destroy mutex: \(strerror(res))")
29 | }
30 | }
31 |
32 | func lock() {
33 | try! aquire(pthread_mutex_lock(&mutex))
34 | }
35 |
36 | func unlock() {
37 | try! aquire(pthread_mutex_unlock(&mutex))
38 | }
39 |
40 | @discardableResult
41 | func locked(_ task: () -> T) -> T {
42 | lock()
43 | defer { unlock() }
44 | return task()
45 | }
46 |
47 | private struct MutexError: Error {
48 | let message: String
49 | }
50 |
51 | private func aquire(_ item: @autoclosure () -> Int32) throws {
52 | let res = item()
53 | if res != 0 {
54 | throw MutexError(message: "\(strerror(res))")
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/ExecutionContext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExecutionContext.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Dispatch
11 |
12 | /// The GCD queue context in which a given Future operation should be performed
13 | public enum ExecutionContext {
14 | /// The main queue, if already on the main queue the task is run immediately
15 | case main
16 | /// The background QoS queue
17 | case background
18 | /// A global queue with the given QoSClass
19 | case global(DispatchQoS.QoSClass)
20 | /// A queue of your choice
21 | case queue(DispatchQueue)
22 |
23 | internal var queue: DispatchQueue {
24 | switch self {
25 | case .main:
26 | return DispatchQueue.main
27 | case .background:
28 | return DispatchQueue.global(qos: .background)
29 | case .global(let qos):
30 | return DispatchQueue.global(qos: qos)
31 | case .queue(let queue):
32 | return queue
33 | }
34 | }
35 |
36 | internal func apply(execute: @escaping () -> Void) {
37 | switch (self, Thread.isMainThread) {
38 | case (.main, true):
39 | execute()
40 | default:
41 | queue.async {
42 | execute()
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Playground.playground/Pages/Basics.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Eventually
3 | import XCPlayground
4 | XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
5 |
6 | /*:
7 | # Eventually
8 |
9 | In order for this playground to work, make sure that you've opened the Eventually.xcworkspace workspace and then selected the playgound. Then build the Eventually-iOS scheme.
10 |
11 | ## Basics
12 |
13 | ### Basic usage & the Result type
14 | */
15 |
16 | /*: A Future represents a value that has not yet materialized, once it is ready we'll call the `resolve` closure with either a `.success` or `.falure` depending on whether the Future resolves to some value or if it encountered an error along the way
17 | */
18 | let basicFuture = Future(resolver: { resolve in
19 | resolve.success(42)
20 | })
21 |
22 | /*: At this point the future may or may not hold a value, so we can use `then()` to get notified when it resolves/materializes. We get delivered a Result enum type, which can hold either a `.success` or `.failure`
23 | */
24 | basicFuture.then { result in
25 | switch result {
26 | case .success(let value):
27 | print("basicFuture is", value)
28 | case .failure(let error):
29 | print("basicFuture failed: ", error)
30 | }
31 | }
32 |
33 | //: ### Wrapping existing API
34 |
35 | //: Do something expensive on a background queue, then bounce back to main
36 | func advancedMathematics(base: Int, completion: @escaping (Int) -> Void) {
37 | DispatchQueue.global(qos: .background).async {
38 | let result = base * 2
39 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
40 | completion(result)
41 | }
42 | }
43 | }
44 | advancedMathematics(base: 42) { value in
45 | // value is 84
46 | }
47 |
48 | //: Existing APIs can easily be wrapped to provide a Future simply by calling the resolve handler once the operation finishes
49 | func futureMathematics(base: Int) -> Future {
50 | return Future { resolve in
51 | advancedMathematics(base: base, completion: { value in
52 | resolve.success(value)
53 | })
54 | }
55 | }
56 |
57 | let asyncFuture = futureMathematics(base: 42)
58 | //: `success()` and `failure()` are provided as chainable shorthand methods
59 | asyncFuture.success { value in
60 | print("ayncFuture is ", value)
61 | }
62 |
63 | //: ### Transforming Futures
64 |
65 | //: The (successful) result of a Future can be mapped into another value. The transform only occurs when the Future value has materialized. Multiple `map()`s (and any other Future method) can be chained
66 | asyncFuture
67 | .map({ $0 / 2})
68 | .map({ n in
69 | return "The meaning is \(n)"
70 | })
71 | .success { value in
72 | print("transformed future is ", value)
73 | }
74 |
75 | //: ### Alternative API
76 |
77 | //: If it suits you implementation better you can use a non-closure based API to resolve Futures
78 |
79 | let future = Future()
80 | future.success { value in
81 | print(value)
82 | }
83 | future.resolve(success: 42)
84 |
85 |
86 | //: [Next: Errors](@next)
87 |
--------------------------------------------------------------------------------
/Eventually.xcodeproj/xcshareddata/xcschemes/Eventually-watchOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
64 |
65 |
71 |
72 |
73 |
74 |
76 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Eventually
4 |
5 | A Swift implementation of a [Future](https://en.wikipedia.org/wiki/Futures_and_promises), which can be used to model and transform asynchronous results while making it easy to bounce results between dispatch queues
6 |
7 | ## Usage
8 |
9 | Futures in Eventually can be used to wrap existing APIs, or to create new APIs using Futures
10 |
11 | ```Swift
12 | func operation(completion: (Int) -> Void) {
13 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
14 | completion(42)
15 | }
16 | }
17 |
18 | Future { resolve in
19 | operation { value
20 | resolve.success(value)
21 | }
22 | }.then { result in
23 | switch result {
24 | case .success(let value):
25 | print("value is", value) // "value is 42"
26 | case .failure(let error):
27 | print("something went wrong:", error)
28 | }
29 | }
30 | ```
31 |
32 | When initializing a Future the closure receives a "resolver", this resolver is simply a closure that you will call with a [FutureResult](/Sources/FutureResult.swift), a Result enum type which can be either `.success` or `.failure`.
33 |
34 | There's also a couple of short-hand methods available
35 |
36 | ```swift
37 | func calculateAge() -> Future {
38 | // ...
39 | }
40 | calculateAge().success { (value: Int) in
41 | print("Success value from calling calculateAge() is", value)
42 | }.failure { error in
43 | print(The Future returned by calculateAge() gave us an error:", error)
44 | }
45 | ```
46 |
47 | A non-closure based API for resolving futures is also available
48 |
49 | ```swift
50 | let future = Future()
51 | future.success { value in
52 | ...
53 | }
54 | future.resolve(success: age)
55 | ```
56 |
57 | ### Mapping values
58 |
59 | With Eventually it is possible to `map()` one Future type to another, allowing us to compose and transform things easily
60 |
61 | ```swift
62 | calculateAge().map({ (value: Int) -> String in
63 | return "Age is \(age)"
64 | }).success { value in
65 | print(value) // "Age is 42"
66 | }
67 | ```
68 |
69 | Like always, chaining is possible so multiple transforms can be done
70 |
71 | ### Evaluation Contexts
72 |
73 | Most of the methods operating on a Future accepts an [EvaluationContext](/Sources/EvaluationContext.swift) that describes what GCD queue the operation should be called on
74 |
75 | ```swift
76 | Future(on: .background) { resolve
77 | // Performed on a background queue (eg `DispatchQueue.global(qos: .background)`)
78 | resolve.success("hello"))
79 | }.map(on: .queue(someCustomQueue)) { value in
80 | // will be called on the supplied DispatchQueue (`someCustomQueue`)
81 | return value + " world"
82 | }.map(on: .main) { value in
83 | // Mapping occurs on the main thread
84 | let label = UILabel()
85 | label.text = value
86 | return text
87 | }.success { label in
88 | // default is the `.main` context
89 | self.view.addSubview(label)
90 | }
91 | ```
92 |
93 | ## Installation
94 |
95 | Eventually is available as a CocoaPod (`pod 'Eventually'`) and the Swift Package Manager. Framework installation is also available by dragging the Eventually.xcodeproj into your project or via Carthage.
96 |
97 | Eventually has no dependencies outside of Foundation and Dispatch (GCD)
98 |
99 | ## License
100 |
101 | See the LICENSE file
102 |
--------------------------------------------------------------------------------
/Sources/Future+Operations.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Future+Operations.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 03/04/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Future {
12 | /// Maps the materialized value to type `U`
13 | /// - parameter on: The ExecutionContext on which the completion closure should be called, defaults to .main
14 | /// - parameter transform: The transform closure that should map the successful value
15 | /// - returns: A new chainable Future instance
16 | ///
17 | /// ```swift
18 | /// someFuture.map({ (age: Int) -> String
19 | /// return "Age: \(age)
20 | /// }).success { print($0) }
21 | @discardableResult
22 | public func map(on context: ExecutionContext = .main, _ transform: @escaping (Value) -> U) -> Future {
23 | let mapped = Future()
24 | self.then(on: context) { result in
25 | switch result {
26 | case .success(let value):
27 | mapped.resolve(success: transform(value))
28 | case .failure(let error):
29 | mapped.resolve(error: error)
30 | }
31 | }
32 | return mapped
33 | }
34 |
35 | /// Combines the successful result of one future with something that takes the successful result as a
36 | /// parameter and returns another future
37 | @discardableResult
38 | public func combine(with other: @escaping (Value) -> Future) -> Future {
39 | let final = Future()
40 | then { result in
41 | switch result {
42 | case .success(let value):
43 | other(value) |> final
44 | case .failure(let error):
45 | final.resolve(error: error)
46 | }
47 |
48 | }
49 | return final
50 | }
51 |
52 | /// Returns a Future of type `T` that returns when all the supplied Future of type `T` finishes, or if a
53 | /// Future returns a failure
54 | ///
55 | /// - parameter futures: List of Futures of type `T`
56 | ///
57 | /// ```swift
58 | /// Future.all([one(), two(), three()]).success { values in
59 | /// // values is an array containing the .success values from the one(), two(), three() futures
60 | /// }
61 | public static func all(_ futures: U) -> Future<[T]> where U.Iterator.Element == Future {
62 | let allFuture = Future<[T]>(on: .background)
63 | let futures = Array(futures)
64 | let mutex = Mutex()
65 | var remaining = futures.count
66 | for future in futures {
67 | future.success(on: .background) { value in
68 | mutex.locked { remaining -= 1 }
69 | if remaining <= 0 {
70 | let values = futures.flatMap({ $0.result?.value })
71 | allFuture.resolve(success: values)
72 | }
73 | }.failure(on: .background) { error in
74 | allFuture.resolve(error: error)
75 | }
76 | }
77 | return allFuture
78 | }
79 | }
80 |
81 | infix operator |>
82 | /// Pipes the result of the left hand side Future into resolving the right hand side Future
83 | internal func |> (left: Future, right: Future) {
84 | left.success { value in
85 | right.resolve(success: value)
86 | }.failure { error in
87 | right.resolve(error: error)
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Eventually.xcodeproj/xcshareddata/xcschemes/Eventually-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Eventually.xcodeproj/xcshareddata/xcschemes/Eventually-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Eventually.xcodeproj/xcshareddata/xcschemes/Eventually-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
69 |
70 |
76 |
77 |
78 |
79 |
80 |
81 |
87 |
88 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/Sources/Future.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Future.swift
3 | // Eventually
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// A Future represent a value that has not yet been calculated, using this class you
12 | /// observe and transform such a value when it has been materialized with a value
13 | public final class Future {
14 | public var result: FutureResult?
15 | public var isCompleted: Bool { return result != nil }
16 |
17 | private var observers: [Observable] = []
18 | private let mutex = Mutex()
19 | private let resolveContext: ExecutionContext
20 |
21 | /// Creates a new future, call the provided resolver when the (async) task completes with
22 | /// either an FutureResult.success or FutureResult.failure in the case of errors
23 | ///
24 | /// - returns: a Future which can be passed around, mapped to another type or materialize its value once
25 | /// the value is available
26 | /// - parameter on: The ExecutionContext on which this Future should be resolved. Defaults to main queue
27 | /// - parameter resolver: The body of the Future which received a resolve closure to be called
28 | /// when the Future is realized
29 | ///
30 | /// ```swift
31 | /// Future { resolve in
32 | /// someAsyncFunc { value in
33 | /// resolve.success(value)
34 | /// }
35 | /// }
36 | public init(on context: ExecutionContext = .main, resolver: @escaping (Resolve) -> Void) {
37 | self.result = nil
38 | self.resolveContext = context
39 |
40 | context.apply {
41 | let resolve = Resolve(closure: { result in
42 | self.complete(with: result)
43 | })
44 | resolver(resolve)
45 | }
46 | }
47 |
48 | /// Creates a new Future that can be resolve at a later time
49 | ///
50 | /// - returns: a Future which can be passed around, mapped to another type or materialize its value once
51 | /// the value is available
52 | /// - parameter on: The ExecutionContext on which this Future should be resolved. Defaults to main queue
53 | /// ```swift
54 | /// let future = Future()
55 | /// ...
56 | /// future.resolve(success: value)
57 | public init(on context: ExecutionContext = .main) {
58 | self.result = nil
59 | self.resolveContext = context
60 | }
61 |
62 | /// Resolve the future with a successful value
63 | ///
64 | /// - parameter success: The value to complete the Future with
65 | public func resolve(success value: Value) {
66 | self.resolveContext.apply {
67 | self.complete(with: .success(value))
68 | }
69 | }
70 |
71 | /// Attempts to resolve the future, turning any thrown errors into a failing future
72 | ///
73 | /// - parameter try: Closure to evaluate for a value, if an error is thrown the future is resolve as a failure
74 | public func resolve(try closure: @escaping () throws -> Value) {
75 | self.resolveContext.apply {
76 | do {
77 | let value = try closure()
78 | self.complete(with: .success(value))
79 | } catch {
80 | self.complete(with: .failure(error))
81 | }
82 | }
83 | }
84 |
85 | /// Resolve the future with an error value
86 | ///
87 | /// - parameter error: The error value to complete the Future with
88 | public func resolve(error: Error) {
89 | self.resolveContext.apply {
90 | self.complete(with: .failure(error))
91 | }
92 | }
93 |
94 | /// Calls the completion closure once the value of the Future is available to be materialized
95 | ///
96 | /// - parameter on: The ExecutionContext on which the completion closure should be called, defaults to .main
97 | /// - parameter completion: The closure which will receive the FutureResult once the Future is materialized
98 | /// - returns: A new chainable Future instance
99 | ///
100 | /// ```swift
101 | /// someFuture.then { result in
102 | /// switch result {
103 | /// case .success(let value):
104 | /// // .. do something with the Value
105 | /// case .failure(let error):
106 | /// // .. error handling
107 | /// }
108 | @discardableResult
109 | public func then(on context: ExecutionContext = .main, _ completion: @escaping (FutureResult) -> Void) -> Future {
110 | let observable = Observable(context: context, observer: completion)
111 |
112 | if let result = self.result {
113 | observable.call(result: result)
114 | } else {
115 | mutex.locked {
116 | self.observers.append(observable)
117 | }
118 | }
119 |
120 | return self
121 | }
122 |
123 | /// Calls the completion closure in case of a succesful Future completion
124 | ///
125 | /// - parameter on: The ExecutionContext on which the completion closure should be called, defaults to .main
126 | /// - parameter completion: The closure which will receive the resulting value once the Future is materialized
127 | /// to a successful value, otherwise in case of an error Result it will not be called
128 | /// - returns: A new chainable Future instance
129 | @discardableResult
130 | public func success(on context: ExecutionContext = .main, _ completion: @escaping (Value) -> Void) -> Future {
131 | return Future { resolve in
132 | self.then(on: context) { result in
133 | switch result {
134 | case .success(let value):
135 | completion(value)
136 | resolve.success(value)
137 | case .failure(let error):
138 | resolve.failure(error)
139 | }
140 | }
141 | }
142 | }
143 |
144 | /// Calls the completion closure in case of a failure Future completion
145 | ///
146 | /// - parameter on: The ExecutionContext on which the completion closure should be called, defaults to .main
147 | /// - parameter completion: The closure which will receive the resulting error if the Future materializes
148 | /// to an error, will not be called otherwise
149 | /// - returns: A new chainable Future instance
150 | @discardableResult
151 | public func failure(on context: ExecutionContext = .main, _ completion: @escaping (Error) -> Void) -> Future {
152 | return Future { resolve in
153 | self.then(on: context) { result in
154 | switch result {
155 | case .success(let value):
156 | resolve.success(value)
157 | case .failure(let error):
158 | completion(error)
159 | resolve.failure(error)
160 | }
161 | }
162 | }
163 | }
164 |
165 | private func complete(with result: FutureResult) {
166 | guard !isCompleted else { return }
167 |
168 | self.result = result
169 |
170 | var observers = mutex.locked { () -> [Observable] in
171 | let reversed = Array(self.observers.reversed())
172 | self.observers.removeAll()
173 | return reversed
174 | }
175 |
176 | while let observer = observers.popLast() {
177 | observer.call(result: result)
178 | }
179 | }
180 | }
181 |
182 | /// :nodoc:
183 | extension Future: CustomStringConvertible {
184 | public var description: String {
185 | return "<\(type(of: self)) result: \(String(describing: result))>"
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/Tests/EventuallyTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventuallyTests.swift
3 | // EventuallyTests
4 | //
5 | // Created by Johan Sørensen on 21/02/2017.
6 | // Copyright © 2017 NRK. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | import Eventually
11 |
12 | class EventuallyTests: XCTestCase {
13 | func testBasics() {
14 | let stringFuture = Future { resolve in
15 | resolve.success("hello")
16 | }
17 |
18 | XCTAssert(stringFuture.isCompleted)
19 | switch stringFuture.result! {
20 | case .success(let value):
21 | XCTAssertEqual(value, "hello")
22 | case .failure:
23 | XCTFail()
24 | }
25 | }
26 |
27 | func testThen() {
28 | successFuture().then { result in
29 | switch result {
30 | case .success(let value):
31 | XCTAssertEqual(value, 42)
32 | case .failure:
33 | XCTFail()
34 | }
35 | }
36 |
37 | failingFuture().then { result in
38 | switch result {
39 | case .success:
40 | XCTFail()
41 | case .failure(let error):
42 | XCTAssert(error is TestError)
43 | }
44 | }
45 | }
46 |
47 | func testAsyncSuccess() {
48 | let wait = expectation(description: "async")
49 |
50 | successAsyncFuture().then { result in
51 | XCTAssertEqual(result.value, Optional(42))
52 | XCTAssertNil(result.error)
53 | wait.fulfill()
54 | }
55 | waitForExpectations(timeout: 0.5, handler: nil)
56 | }
57 |
58 | func testSuccessFailureSugar() {
59 | let wait = expectation(description: "async")
60 |
61 | successAsyncFuture()
62 | .success { value in
63 | XCTAssertEqual(value, 42)
64 | wait.fulfill()
65 | }.failure { _ in
66 | XCTFail("should never be reached")
67 | }
68 | waitForExpectations(timeout: 0.5, handler: nil)
69 | }
70 |
71 | func testFailingSuccessFailureSugar() {
72 | let wait = expectation(description: "async")
73 |
74 | failingAsyncFuture()
75 | .success { _ in
76 | XCTFail("should never be reached")
77 | }.failure { error in
78 | XCTAssert(error is TestError)
79 | wait.fulfill()
80 | }
81 | waitForExpectations(timeout: 0.5, handler: nil)
82 | }
83 |
84 | func testAsyncFailure() {
85 | let wait = expectation(description: "async")
86 |
87 | failingAsyncFuture().then { result in
88 | XCTAssertNil(result.value)
89 | XCTAssertNotNil(result.error)
90 | wait.fulfill()
91 | }
92 | waitForExpectations(timeout: 0.5, handler: nil)
93 | }
94 |
95 | func testResolvingOnNonMailExecutionContext() {
96 | let future = Future(on: .background) { resolve in
97 | XCTAssertFalse(Thread.isMainThread)
98 | self.operation(completion: { val in
99 | resolve.success(val)
100 | })
101 | }
102 |
103 | let wait = expectation(description: "async")
104 |
105 | future.then { result in
106 | XCTAssertTrue(Thread.isMainThread)
107 | wait.fulfill()
108 | }
109 | waitForExpectations(timeout: 0.5, handler: nil)
110 | }
111 |
112 | func testFulfillingMailExecutionContext() {
113 | let future = Future(on: .main) { resolve in
114 | XCTAssertTrue(Thread.isMainThread)
115 | self.operation(completion: { val in
116 | resolve.success(val)
117 | })
118 | }
119 |
120 | let wait = expectation(description: "async")
121 |
122 | future.then(on: .background) { result in
123 | XCTAssertFalse(Thread.isMainThread)
124 | wait.fulfill()
125 | }
126 | waitForExpectations(timeout: 0.5, handler: nil)
127 | }
128 |
129 | func testAsyncMapping() {
130 | let wait = expectation(description: "async")
131 |
132 | successAsyncFuture()
133 | .map({ $0 * 2 })
134 | .then({ result in
135 | XCTAssertEqual(result.value, Optional(84))
136 | wait.fulfill()
137 | })
138 |
139 | waitForExpectations(timeout: 0.5, handler: nil)
140 | }
141 |
142 | func testAsyncMappingOnContext() {
143 | let wait = expectation(description: "async")
144 |
145 | successAsyncFuture()
146 | .map(on: .background, { (value: Int) -> Int in
147 | XCTAssertFalse(Thread.isMainThread)
148 | return value * 2
149 | })
150 | .then({ result in
151 | XCTAssertEqual(result.value, Optional(84))
152 | wait.fulfill()
153 | })
154 |
155 | waitForExpectations(timeout: 0.5, handler: nil)
156 | }
157 |
158 | func testAll() {
159 | let wait = expectation(description: "async")
160 |
161 | var count = 0
162 | Future.all([
163 | successAsyncFuture(value: 2).success({ _ in count += 1 }),
164 | successAsyncFuture(value: 4).success({ _ in count += 1 }),
165 | successAsyncFuture(value: 6).success({ _ in count += 1 }),
166 | ]).success { values in
167 | // all done
168 | XCTAssertEqual(count, 3)
169 | XCTAssertEqual(values, [2, 4, 6])
170 | wait.fulfill()
171 | }
172 |
173 | waitForExpectations(timeout: 0.5, handler: nil)
174 | }
175 |
176 | func testAllFailure() {
177 | let wait = expectation(description: "async")
178 |
179 | var count = 0
180 | func run() -> Future {
181 | return Future { resolve in
182 | DispatchQueue.global().async {
183 | count += 1
184 | resolve.success(1)
185 | }
186 | }
187 | }
188 |
189 | Future.all([
190 | run(),
191 | failingFuture(),
192 | run(),
193 | ]).failure { error in
194 | XCTAssertEqual(count, 2)
195 | wait.fulfill()
196 | }
197 |
198 | waitForExpectations(timeout: 0.5)
199 | }
200 |
201 | func testNonClosureResolveSuccess() {
202 | let future = Future()
203 |
204 | let wait = expectation(description: "async")
205 | future.success { value in
206 | XCTAssertEqual(value, 42)
207 | wait.fulfill()
208 | }
209 |
210 | future.resolve(success: 42)
211 | waitForExpectations(timeout: 0.1, handler: nil)
212 | }
213 |
214 | func testNonClosureResolveFailure() {
215 | let future = Future()
216 |
217 | let wait = expectation(description: "async")
218 | future.failure { error in
219 | XCTAssert(error is TestError)
220 | wait.fulfill()
221 | }
222 |
223 | future.resolve(error: TestError.fail)
224 | waitForExpectations(timeout: 0.1, handler: nil)
225 | }
226 |
227 | func testFuturesCanOnlyBeResolvedOnce() {
228 | let future = Future()
229 | future.resolve(success: 42)
230 | XCTAssertEqual(future.result!.value, 42)
231 | future.resolve(success: 666)
232 | XCTAssertEqual(future.result!.value, 42)
233 | }
234 |
235 | func testThrowingFuture() {
236 | let wait1 = expectation(description: "async")
237 | let successFuture = Future()
238 | successFuture.success { value in
239 | XCTAssertEqual(value, 42)
240 | wait1.fulfill()
241 | }
242 | successFuture.resolve(try: {
243 | return 42
244 | })
245 |
246 | let wait2 = expectation(description: "async2")
247 | let failingFuture = Future()
248 | failingFuture.failure { error in
249 | XCTAssert(failingFuture.result!.error is TestError)
250 | XCTAssertEqual(failingFuture.result!.error as! TestError, TestError.fail)
251 | wait2.fulfill()
252 | }
253 | failingFuture.resolve(try: {
254 | throw TestError.fail
255 | })
256 |
257 | waitForExpectations(timeout: 0.1, handler: nil)
258 | }
259 |
260 | func testCombine() {
261 | func gen(shouldFail: Bool = false) -> Future {
262 | let future = Future()
263 | if !shouldFail {
264 | future.resolve(success: 42)
265 | } else {
266 | future.resolve(error: TestError.fail)
267 | }
268 |
269 | return future
270 | }
271 | func stringy(value: Int) -> Future {
272 | return Future(on: .background) { resolve in
273 | resolve.success("value is \(value)")
274 | }
275 | }
276 | func stringyFail(value: Int) -> Future {
277 | return Future(on: .background) { resolve in
278 | resolve.failure(TestError.fail2)
279 | }
280 | }
281 |
282 | let wait1 = expectation(description: "async")
283 | gen().combine(with: stringy).success { value in
284 | XCTAssertEqual("value is 42", value)
285 | wait1.fulfill()
286 | }
287 |
288 | let wait2 = expectation(description: "async")
289 | gen(shouldFail: true).combine(with: stringy).success { value in
290 | XCTFail()
291 | }.failure { error in
292 | XCTAssert(error is TestError)
293 | XCTAssertEqual(error as! TestError, TestError.fail)
294 | wait2.fulfill()
295 | }
296 |
297 | let wait3 = expectation(description: "async")
298 | gen().combine(with: stringyFail).success { value in
299 | XCTFail()
300 | }.failure { error in
301 | XCTAssert(error is TestError)
302 | XCTAssertEqual(error as! TestError, TestError.fail2)
303 | wait3.fulfill()
304 | }
305 |
306 | waitForExpectations(timeout: 0.1, handler: nil)
307 | }
308 |
309 | // MARK: - Helpers
310 |
311 | func operation(value: Int = 42, completion: @escaping (Int) -> Void) {
312 | DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(256)) {
313 | completion(value)
314 | }
315 | }
316 |
317 | func successAsyncFuture(value: Int = 42) -> Future {
318 | return Future { resolve in
319 | self.operation(value: value, completion: { val in
320 | resolve.success(val)
321 | })
322 | }
323 | }
324 |
325 | func successFuture() -> Future {
326 | return Future { resolve in
327 | resolve.success(42)
328 | }
329 | }
330 |
331 | enum TestError: Error {
332 | case fail
333 | case fail2
334 | }
335 |
336 | func failingFuture() -> Future {
337 | return Future { resolve in
338 | resolve.failure(TestError.fail)
339 | }
340 | }
341 |
342 | func failingAsyncFuture() -> Future {
343 | return Future { resolve in
344 | DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(256)) {
345 | resolve.failure(TestError.fail)
346 | }
347 | }
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/Eventually.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 47;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 04171ED11E5CC05700E1C640 /* EventuallyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ECF1E5CC05100E1C640 /* EventuallyTests.swift */; };
11 | 04171ED21E5CC05700E1C640 /* EventuallyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ECF1E5CC05100E1C640 /* EventuallyTests.swift */; };
12 | 04171ED31E5CC05800E1C640 /* EventuallyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ECF1E5CC05100E1C640 /* EventuallyTests.swift */; };
13 | 04171ED81E5CC06100E1C640 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */; };
14 | 04171ED91E5CC06100E1C640 /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED51E5CC06100E1C640 /* Future.swift */; };
15 | 04171EDA1E5CC06100E1C640 /* FutureResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED61E5CC06100E1C640 /* FutureResult.swift */; };
16 | 04171EDB1E5CC06100E1C640 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED71E5CC06100E1C640 /* Observable.swift */; };
17 | 04171EDC1E5CC06D00E1C640 /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED51E5CC06100E1C640 /* Future.swift */; };
18 | 04171EDD1E5CC06D00E1C640 /* FutureResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED61E5CC06100E1C640 /* FutureResult.swift */; };
19 | 04171EDE1E5CC06D00E1C640 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */; };
20 | 04171EDF1E5CC06D00E1C640 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED71E5CC06100E1C640 /* Observable.swift */; };
21 | 04171EE01E5CC06D00E1C640 /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED51E5CC06100E1C640 /* Future.swift */; };
22 | 04171EE11E5CC06D00E1C640 /* FutureResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED61E5CC06100E1C640 /* FutureResult.swift */; };
23 | 04171EE21E5CC06D00E1C640 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */; };
24 | 04171EE31E5CC06D00E1C640 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED71E5CC06100E1C640 /* Observable.swift */; };
25 | 04171EE41E5CC06E00E1C640 /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED51E5CC06100E1C640 /* Future.swift */; };
26 | 04171EE51E5CC06E00E1C640 /* FutureResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED61E5CC06100E1C640 /* FutureResult.swift */; };
27 | 04171EE61E5CC06E00E1C640 /* ExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */; };
28 | 04171EE71E5CC06E00E1C640 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171ED71E5CC06100E1C640 /* Observable.swift */; };
29 | 04171EE91E5CDC9500E1C640 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171EE81E5CDC9500E1C640 /* Mutex.swift */; };
30 | 04171EEA1E5CDC9500E1C640 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171EE81E5CDC9500E1C640 /* Mutex.swift */; };
31 | 04171EEB1E5CDC9500E1C640 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171EE81E5CDC9500E1C640 /* Mutex.swift */; };
32 | 04171EEC1E5CDC9500E1C640 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04171EE81E5CDC9500E1C640 /* Mutex.swift */; };
33 | 52D6D9871BEFF229002C0205 /* Eventually.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* Eventually.framework */; };
34 | D917F6B01E928638000B1232 /* Future+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D917F6AF1E928638000B1232 /* Future+Operations.swift */; };
35 | D917F6B11E928638000B1232 /* Future+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D917F6AF1E928638000B1232 /* Future+Operations.swift */; };
36 | D917F6B21E928638000B1232 /* Future+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D917F6AF1E928638000B1232 /* Future+Operations.swift */; };
37 | D917F6B31E928638000B1232 /* Future+Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D917F6AF1E928638000B1232 /* Future+Operations.swift */; };
38 | D9D9DB8C1E66B2FF0033406B /* Resolve.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9D9DB8B1E66B2FF0033406B /* Resolve.swift */; };
39 | D9D9DB8D1E66B2FF0033406B /* Resolve.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9D9DB8B1E66B2FF0033406B /* Resolve.swift */; };
40 | D9D9DB8E1E66B2FF0033406B /* Resolve.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9D9DB8B1E66B2FF0033406B /* Resolve.swift */; };
41 | D9D9DB8F1E66B2FF0033406B /* Resolve.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9D9DB8B1E66B2FF0033406B /* Resolve.swift */; };
42 | DD7502881C68FEDE006590AF /* Eventually.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6DA0F1BF000BD002C0205 /* Eventually.framework */; };
43 | DD7502921C690C7A006590AF /* Eventually.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D9F01BEFFFBE002C0205 /* Eventually.framework */; };
44 | /* End PBXBuildFile section */
45 |
46 | /* Begin PBXContainerItemProxy section */
47 | 52D6D9881BEFF229002C0205 /* PBXContainerItemProxy */ = {
48 | isa = PBXContainerItemProxy;
49 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
50 | proxyType = 1;
51 | remoteGlobalIDString = 52D6D97B1BEFF229002C0205;
52 | remoteInfo = Eventually;
53 | };
54 | DD7502801C68FCFC006590AF /* PBXContainerItemProxy */ = {
55 | isa = PBXContainerItemProxy;
56 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
57 | proxyType = 1;
58 | remoteGlobalIDString = 52D6DA0E1BF000BD002C0205;
59 | remoteInfo = "Eventually-macOS";
60 | };
61 | DD7502931C690C7A006590AF /* PBXContainerItemProxy */ = {
62 | isa = PBXContainerItemProxy;
63 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
64 | proxyType = 1;
65 | remoteGlobalIDString = 52D6D9EF1BEFFFBE002C0205;
66 | remoteInfo = "Eventually-tvOS";
67 | };
68 | /* End PBXContainerItemProxy section */
69 |
70 | /* Begin PBXFileReference section */
71 | 04171ECF1E5CC05100E1C640 /* EventuallyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventuallyTests.swift; sourceTree = ""; };
72 | 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExecutionContext.swift; sourceTree = ""; };
73 | 04171ED51E5CC06100E1C640 /* Future.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Future.swift; sourceTree = ""; };
74 | 04171ED61E5CC06100E1C640 /* FutureResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FutureResult.swift; sourceTree = ""; };
75 | 04171ED71E5CC06100E1C640 /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = ""; };
76 | 04171EE81E5CDC9500E1C640 /* Mutex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mutex.swift; sourceTree = ""; };
77 | 52D6D97C1BEFF229002C0205 /* Eventually.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eventually.framework; sourceTree = BUILT_PRODUCTS_DIR; };
78 | 52D6D9861BEFF229002C0205 /* Eventually-iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Eventually-iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
79 | 52D6D9E21BEFFF6E002C0205 /* Eventually.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eventually.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80 | 52D6D9F01BEFFFBE002C0205 /* Eventually.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eventually.framework; sourceTree = BUILT_PRODUCTS_DIR; };
81 | 52D6DA0F1BF000BD002C0205 /* Eventually.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eventually.framework; sourceTree = BUILT_PRODUCTS_DIR; };
82 | AD2FAA261CD0B6D800659CF4 /* Eventually.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Eventually.plist; sourceTree = ""; };
83 | AD2FAA281CD0B6E100659CF4 /* EventuallyTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = EventuallyTests.plist; sourceTree = ""; };
84 | D917F6AF1E928638000B1232 /* Future+Operations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Future+Operations.swift"; sourceTree = ""; };
85 | D9ADA01F1E694B0E003C91BD /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
86 | D9D9DB8B1E66B2FF0033406B /* Resolve.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Resolve.swift; sourceTree = ""; };
87 | DD75027A1C68FCFC006590AF /* Eventually-macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Eventually-macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
88 | DD75028D1C690C7A006590AF /* Eventually-tvOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Eventually-tvOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
89 | /* End PBXFileReference section */
90 |
91 | /* Begin PBXFrameworksBuildPhase section */
92 | 52D6D9781BEFF229002C0205 /* Frameworks */ = {
93 | isa = PBXFrameworksBuildPhase;
94 | buildActionMask = 2147483647;
95 | files = (
96 | );
97 | runOnlyForDeploymentPostprocessing = 0;
98 | };
99 | 52D6D9831BEFF229002C0205 /* Frameworks */ = {
100 | isa = PBXFrameworksBuildPhase;
101 | buildActionMask = 2147483647;
102 | files = (
103 | 52D6D9871BEFF229002C0205 /* Eventually.framework in Frameworks */,
104 | );
105 | runOnlyForDeploymentPostprocessing = 0;
106 | };
107 | 52D6D9DE1BEFFF6E002C0205 /* Frameworks */ = {
108 | isa = PBXFrameworksBuildPhase;
109 | buildActionMask = 2147483647;
110 | files = (
111 | );
112 | runOnlyForDeploymentPostprocessing = 0;
113 | };
114 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */ = {
115 | isa = PBXFrameworksBuildPhase;
116 | buildActionMask = 2147483647;
117 | files = (
118 | );
119 | runOnlyForDeploymentPostprocessing = 0;
120 | };
121 | 52D6DA0B1BF000BD002C0205 /* Frameworks */ = {
122 | isa = PBXFrameworksBuildPhase;
123 | buildActionMask = 2147483647;
124 | files = (
125 | );
126 | runOnlyForDeploymentPostprocessing = 0;
127 | };
128 | DD7502771C68FCFC006590AF /* Frameworks */ = {
129 | isa = PBXFrameworksBuildPhase;
130 | buildActionMask = 2147483647;
131 | files = (
132 | DD7502881C68FEDE006590AF /* Eventually.framework in Frameworks */,
133 | );
134 | runOnlyForDeploymentPostprocessing = 0;
135 | };
136 | DD75028A1C690C7A006590AF /* Frameworks */ = {
137 | isa = PBXFrameworksBuildPhase;
138 | buildActionMask = 2147483647;
139 | files = (
140 | DD7502921C690C7A006590AF /* Eventually.framework in Frameworks */,
141 | );
142 | runOnlyForDeploymentPostprocessing = 0;
143 | };
144 | /* End PBXFrameworksBuildPhase section */
145 |
146 | /* Begin PBXGroup section */
147 | 04171ECD1E5CBFD600E1C640 /* Sources */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 04171ED51E5CC06100E1C640 /* Future.swift */,
151 | D917F6AF1E928638000B1232 /* Future+Operations.swift */,
152 | 04171ED61E5CC06100E1C640 /* FutureResult.swift */,
153 | 04171ED41E5CC06100E1C640 /* ExecutionContext.swift */,
154 | D9D9DB8B1E66B2FF0033406B /* Resolve.swift */,
155 | 04171ED71E5CC06100E1C640 /* Observable.swift */,
156 | 04171EE81E5CDC9500E1C640 /* Mutex.swift */,
157 | );
158 | path = Sources;
159 | sourceTree = "";
160 | };
161 | 04171ECE1E5CBFDD00E1C640 /* Tests */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 04171ECF1E5CC05100E1C640 /* EventuallyTests.swift */,
165 | );
166 | path = Tests;
167 | sourceTree = "";
168 | };
169 | 52D6D9721BEFF229002C0205 = {
170 | isa = PBXGroup;
171 | children = (
172 | D9ADA01F1E694B0E003C91BD /* README.md */,
173 | 04171ECD1E5CBFD600E1C640 /* Sources */,
174 | 04171ECE1E5CBFDD00E1C640 /* Tests */,
175 | 52D6D99C1BEFF38C002C0205 /* Configs */,
176 | 52D6D97D1BEFF229002C0205 /* Products */,
177 | );
178 | sourceTree = "";
179 | };
180 | 52D6D97D1BEFF229002C0205 /* Products */ = {
181 | isa = PBXGroup;
182 | children = (
183 | 52D6D97C1BEFF229002C0205 /* Eventually.framework */,
184 | 52D6D9861BEFF229002C0205 /* Eventually-iOS Tests.xctest */,
185 | 52D6D9E21BEFFF6E002C0205 /* Eventually.framework */,
186 | 52D6D9F01BEFFFBE002C0205 /* Eventually.framework */,
187 | 52D6DA0F1BF000BD002C0205 /* Eventually.framework */,
188 | DD75027A1C68FCFC006590AF /* Eventually-macOS Tests.xctest */,
189 | DD75028D1C690C7A006590AF /* Eventually-tvOS Tests.xctest */,
190 | );
191 | name = Products;
192 | sourceTree = "";
193 | };
194 | 52D6D99C1BEFF38C002C0205 /* Configs */ = {
195 | isa = PBXGroup;
196 | children = (
197 | DD7502721C68FC1B006590AF /* Frameworks */,
198 | DD7502731C68FC20006590AF /* Tests */,
199 | );
200 | path = Configs;
201 | sourceTree = "";
202 | };
203 | DD7502721C68FC1B006590AF /* Frameworks */ = {
204 | isa = PBXGroup;
205 | children = (
206 | AD2FAA261CD0B6D800659CF4 /* Eventually.plist */,
207 | );
208 | name = Frameworks;
209 | sourceTree = "";
210 | };
211 | DD7502731C68FC20006590AF /* Tests */ = {
212 | isa = PBXGroup;
213 | children = (
214 | AD2FAA281CD0B6E100659CF4 /* EventuallyTests.plist */,
215 | );
216 | name = Tests;
217 | sourceTree = "";
218 | };
219 | /* End PBXGroup section */
220 |
221 | /* Begin PBXHeadersBuildPhase section */
222 | 52D6D9791BEFF229002C0205 /* Headers */ = {
223 | isa = PBXHeadersBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | );
227 | runOnlyForDeploymentPostprocessing = 0;
228 | };
229 | 52D6D9DF1BEFFF6E002C0205 /* Headers */ = {
230 | isa = PBXHeadersBuildPhase;
231 | buildActionMask = 2147483647;
232 | files = (
233 | );
234 | runOnlyForDeploymentPostprocessing = 0;
235 | };
236 | 52D6D9ED1BEFFFBE002C0205 /* Headers */ = {
237 | isa = PBXHeadersBuildPhase;
238 | buildActionMask = 2147483647;
239 | files = (
240 | );
241 | runOnlyForDeploymentPostprocessing = 0;
242 | };
243 | 52D6DA0C1BF000BD002C0205 /* Headers */ = {
244 | isa = PBXHeadersBuildPhase;
245 | buildActionMask = 2147483647;
246 | files = (
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | };
250 | /* End PBXHeadersBuildPhase section */
251 |
252 | /* Begin PBXNativeTarget section */
253 | 52D6D97B1BEFF229002C0205 /* Eventually-iOS */ = {
254 | isa = PBXNativeTarget;
255 | buildConfigurationList = 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Eventually-iOS" */;
256 | buildPhases = (
257 | 52D6D9771BEFF229002C0205 /* Sources */,
258 | 52D6D9781BEFF229002C0205 /* Frameworks */,
259 | 52D6D9791BEFF229002C0205 /* Headers */,
260 | 52D6D97A1BEFF229002C0205 /* Resources */,
261 | );
262 | buildRules = (
263 | );
264 | dependencies = (
265 | );
266 | name = "Eventually-iOS";
267 | productName = Eventually;
268 | productReference = 52D6D97C1BEFF229002C0205 /* Eventually.framework */;
269 | productType = "com.apple.product-type.framework";
270 | };
271 | 52D6D9851BEFF229002C0205 /* Eventually-iOS Tests */ = {
272 | isa = PBXNativeTarget;
273 | buildConfigurationList = 52D6D9931BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Eventually-iOS Tests" */;
274 | buildPhases = (
275 | 52D6D9821BEFF229002C0205 /* Sources */,
276 | 52D6D9831BEFF229002C0205 /* Frameworks */,
277 | 52D6D9841BEFF229002C0205 /* Resources */,
278 | );
279 | buildRules = (
280 | );
281 | dependencies = (
282 | 52D6D9891BEFF229002C0205 /* PBXTargetDependency */,
283 | );
284 | name = "Eventually-iOS Tests";
285 | productName = EventuallyTests;
286 | productReference = 52D6D9861BEFF229002C0205 /* Eventually-iOS Tests.xctest */;
287 | productType = "com.apple.product-type.bundle.unit-test";
288 | };
289 | 52D6D9E11BEFFF6E002C0205 /* Eventually-watchOS */ = {
290 | isa = PBXNativeTarget;
291 | buildConfigurationList = 52D6D9E71BEFFF6E002C0205 /* Build configuration list for PBXNativeTarget "Eventually-watchOS" */;
292 | buildPhases = (
293 | 52D6D9DD1BEFFF6E002C0205 /* Sources */,
294 | 52D6D9DE1BEFFF6E002C0205 /* Frameworks */,
295 | 52D6D9DF1BEFFF6E002C0205 /* Headers */,
296 | 52D6D9E01BEFFF6E002C0205 /* Resources */,
297 | );
298 | buildRules = (
299 | );
300 | dependencies = (
301 | );
302 | name = "Eventually-watchOS";
303 | productName = "Eventually-watchOS";
304 | productReference = 52D6D9E21BEFFF6E002C0205 /* Eventually.framework */;
305 | productType = "com.apple.product-type.framework";
306 | };
307 | 52D6D9EF1BEFFFBE002C0205 /* Eventually-tvOS */ = {
308 | isa = PBXNativeTarget;
309 | buildConfigurationList = 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "Eventually-tvOS" */;
310 | buildPhases = (
311 | 52D6D9EB1BEFFFBE002C0205 /* Sources */,
312 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */,
313 | 52D6D9ED1BEFFFBE002C0205 /* Headers */,
314 | 52D6D9EE1BEFFFBE002C0205 /* Resources */,
315 | );
316 | buildRules = (
317 | );
318 | dependencies = (
319 | );
320 | name = "Eventually-tvOS";
321 | productName = "Eventually-tvOS";
322 | productReference = 52D6D9F01BEFFFBE002C0205 /* Eventually.framework */;
323 | productType = "com.apple.product-type.framework";
324 | };
325 | 52D6DA0E1BF000BD002C0205 /* Eventually-macOS */ = {
326 | isa = PBXNativeTarget;
327 | buildConfigurationList = 52D6DA201BF000BD002C0205 /* Build configuration list for PBXNativeTarget "Eventually-macOS" */;
328 | buildPhases = (
329 | 52D6DA0A1BF000BD002C0205 /* Sources */,
330 | 52D6DA0B1BF000BD002C0205 /* Frameworks */,
331 | 52D6DA0C1BF000BD002C0205 /* Headers */,
332 | 52D6DA0D1BF000BD002C0205 /* Resources */,
333 | );
334 | buildRules = (
335 | );
336 | dependencies = (
337 | );
338 | name = "Eventually-macOS";
339 | productName = "Eventually-macOS";
340 | productReference = 52D6DA0F1BF000BD002C0205 /* Eventually.framework */;
341 | productType = "com.apple.product-type.framework";
342 | };
343 | DD7502791C68FCFC006590AF /* Eventually-macOS Tests */ = {
344 | isa = PBXNativeTarget;
345 | buildConfigurationList = DD7502821C68FCFC006590AF /* Build configuration list for PBXNativeTarget "Eventually-macOS Tests" */;
346 | buildPhases = (
347 | DD7502761C68FCFC006590AF /* Sources */,
348 | DD7502771C68FCFC006590AF /* Frameworks */,
349 | DD7502781C68FCFC006590AF /* Resources */,
350 | );
351 | buildRules = (
352 | );
353 | dependencies = (
354 | DD7502811C68FCFC006590AF /* PBXTargetDependency */,
355 | );
356 | name = "Eventually-macOS Tests";
357 | productName = "Eventually-OS Tests";
358 | productReference = DD75027A1C68FCFC006590AF /* Eventually-macOS Tests.xctest */;
359 | productType = "com.apple.product-type.bundle.unit-test";
360 | };
361 | DD75028C1C690C7A006590AF /* Eventually-tvOS Tests */ = {
362 | isa = PBXNativeTarget;
363 | buildConfigurationList = DD7502951C690C7A006590AF /* Build configuration list for PBXNativeTarget "Eventually-tvOS Tests" */;
364 | buildPhases = (
365 | DD7502891C690C7A006590AF /* Sources */,
366 | DD75028A1C690C7A006590AF /* Frameworks */,
367 | DD75028B1C690C7A006590AF /* Resources */,
368 | );
369 | buildRules = (
370 | );
371 | dependencies = (
372 | DD7502941C690C7A006590AF /* PBXTargetDependency */,
373 | );
374 | name = "Eventually-tvOS Tests";
375 | productName = "Eventually-tvOS Tests";
376 | productReference = DD75028D1C690C7A006590AF /* Eventually-tvOS Tests.xctest */;
377 | productType = "com.apple.product-type.bundle.unit-test";
378 | };
379 | /* End PBXNativeTarget section */
380 |
381 | /* Begin PBXProject section */
382 | 52D6D9731BEFF229002C0205 /* Project object */ = {
383 | isa = PBXProject;
384 | attributes = {
385 | LastSwiftUpdateCheck = 0720;
386 | LastUpgradeCheck = 0900;
387 | ORGANIZATIONNAME = NRK;
388 | TargetAttributes = {
389 | 52D6D97B1BEFF229002C0205 = {
390 | CreatedOnToolsVersion = 7.1;
391 | LastSwiftMigration = 0900;
392 | };
393 | 52D6D9851BEFF229002C0205 = {
394 | CreatedOnToolsVersion = 7.1;
395 | LastSwiftMigration = 0900;
396 | };
397 | 52D6D9E11BEFFF6E002C0205 = {
398 | CreatedOnToolsVersion = 7.1;
399 | LastSwiftMigration = 0800;
400 | };
401 | 52D6D9EF1BEFFFBE002C0205 = {
402 | CreatedOnToolsVersion = 7.1;
403 | LastSwiftMigration = 0800;
404 | };
405 | 52D6DA0E1BF000BD002C0205 = {
406 | CreatedOnToolsVersion = 7.1;
407 | LastSwiftMigration = 0800;
408 | };
409 | DD7502791C68FCFC006590AF = {
410 | CreatedOnToolsVersion = 7.2.1;
411 | LastSwiftMigration = 0800;
412 | };
413 | DD75028C1C690C7A006590AF = {
414 | CreatedOnToolsVersion = 7.2.1;
415 | LastSwiftMigration = 0800;
416 | };
417 | };
418 | };
419 | buildConfigurationList = 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "Eventually" */;
420 | compatibilityVersion = "Xcode 6.3";
421 | developmentRegion = English;
422 | hasScannedForEncodings = 0;
423 | knownRegions = (
424 | en,
425 | );
426 | mainGroup = 52D6D9721BEFF229002C0205;
427 | productRefGroup = 52D6D97D1BEFF229002C0205 /* Products */;
428 | projectDirPath = "";
429 | projectRoot = "";
430 | targets = (
431 | 52D6D97B1BEFF229002C0205 /* Eventually-iOS */,
432 | 52D6DA0E1BF000BD002C0205 /* Eventually-macOS */,
433 | 52D6D9E11BEFFF6E002C0205 /* Eventually-watchOS */,
434 | 52D6D9EF1BEFFFBE002C0205 /* Eventually-tvOS */,
435 | 52D6D9851BEFF229002C0205 /* Eventually-iOS Tests */,
436 | DD7502791C68FCFC006590AF /* Eventually-macOS Tests */,
437 | DD75028C1C690C7A006590AF /* Eventually-tvOS Tests */,
438 | );
439 | };
440 | /* End PBXProject section */
441 |
442 | /* Begin PBXResourcesBuildPhase section */
443 | 52D6D97A1BEFF229002C0205 /* Resources */ = {
444 | isa = PBXResourcesBuildPhase;
445 | buildActionMask = 2147483647;
446 | files = (
447 | );
448 | runOnlyForDeploymentPostprocessing = 0;
449 | };
450 | 52D6D9841BEFF229002C0205 /* Resources */ = {
451 | isa = PBXResourcesBuildPhase;
452 | buildActionMask = 2147483647;
453 | files = (
454 | );
455 | runOnlyForDeploymentPostprocessing = 0;
456 | };
457 | 52D6D9E01BEFFF6E002C0205 /* Resources */ = {
458 | isa = PBXResourcesBuildPhase;
459 | buildActionMask = 2147483647;
460 | files = (
461 | );
462 | runOnlyForDeploymentPostprocessing = 0;
463 | };
464 | 52D6D9EE1BEFFFBE002C0205 /* Resources */ = {
465 | isa = PBXResourcesBuildPhase;
466 | buildActionMask = 2147483647;
467 | files = (
468 | );
469 | runOnlyForDeploymentPostprocessing = 0;
470 | };
471 | 52D6DA0D1BF000BD002C0205 /* Resources */ = {
472 | isa = PBXResourcesBuildPhase;
473 | buildActionMask = 2147483647;
474 | files = (
475 | );
476 | runOnlyForDeploymentPostprocessing = 0;
477 | };
478 | DD7502781C68FCFC006590AF /* Resources */ = {
479 | isa = PBXResourcesBuildPhase;
480 | buildActionMask = 2147483647;
481 | files = (
482 | );
483 | runOnlyForDeploymentPostprocessing = 0;
484 | };
485 | DD75028B1C690C7A006590AF /* Resources */ = {
486 | isa = PBXResourcesBuildPhase;
487 | buildActionMask = 2147483647;
488 | files = (
489 | );
490 | runOnlyForDeploymentPostprocessing = 0;
491 | };
492 | /* End PBXResourcesBuildPhase section */
493 |
494 | /* Begin PBXSourcesBuildPhase section */
495 | 52D6D9771BEFF229002C0205 /* Sources */ = {
496 | isa = PBXSourcesBuildPhase;
497 | buildActionMask = 2147483647;
498 | files = (
499 | D9D9DB8C1E66B2FF0033406B /* Resolve.swift in Sources */,
500 | 04171EE91E5CDC9500E1C640 /* Mutex.swift in Sources */,
501 | 04171EDB1E5CC06100E1C640 /* Observable.swift in Sources */,
502 | 04171ED91E5CC06100E1C640 /* Future.swift in Sources */,
503 | 04171EDA1E5CC06100E1C640 /* FutureResult.swift in Sources */,
504 | D917F6B01E928638000B1232 /* Future+Operations.swift in Sources */,
505 | 04171ED81E5CC06100E1C640 /* ExecutionContext.swift in Sources */,
506 | );
507 | runOnlyForDeploymentPostprocessing = 0;
508 | };
509 | 52D6D9821BEFF229002C0205 /* Sources */ = {
510 | isa = PBXSourcesBuildPhase;
511 | buildActionMask = 2147483647;
512 | files = (
513 | 04171ED11E5CC05700E1C640 /* EventuallyTests.swift in Sources */,
514 | );
515 | runOnlyForDeploymentPostprocessing = 0;
516 | };
517 | 52D6D9DD1BEFFF6E002C0205 /* Sources */ = {
518 | isa = PBXSourcesBuildPhase;
519 | buildActionMask = 2147483647;
520 | files = (
521 | D9D9DB8E1E66B2FF0033406B /* Resolve.swift in Sources */,
522 | 04171EEB1E5CDC9500E1C640 /* Mutex.swift in Sources */,
523 | 04171EE31E5CC06D00E1C640 /* Observable.swift in Sources */,
524 | 04171EE01E5CC06D00E1C640 /* Future.swift in Sources */,
525 | 04171EE21E5CC06D00E1C640 /* ExecutionContext.swift in Sources */,
526 | D917F6B21E928638000B1232 /* Future+Operations.swift in Sources */,
527 | 04171EE11E5CC06D00E1C640 /* FutureResult.swift in Sources */,
528 | );
529 | runOnlyForDeploymentPostprocessing = 0;
530 | };
531 | 52D6D9EB1BEFFFBE002C0205 /* Sources */ = {
532 | isa = PBXSourcesBuildPhase;
533 | buildActionMask = 2147483647;
534 | files = (
535 | D9D9DB8F1E66B2FF0033406B /* Resolve.swift in Sources */,
536 | 04171EEC1E5CDC9500E1C640 /* Mutex.swift in Sources */,
537 | 04171EDF1E5CC06D00E1C640 /* Observable.swift in Sources */,
538 | 04171EDC1E5CC06D00E1C640 /* Future.swift in Sources */,
539 | 04171EDE1E5CC06D00E1C640 /* ExecutionContext.swift in Sources */,
540 | D917F6B31E928638000B1232 /* Future+Operations.swift in Sources */,
541 | 04171EDD1E5CC06D00E1C640 /* FutureResult.swift in Sources */,
542 | );
543 | runOnlyForDeploymentPostprocessing = 0;
544 | };
545 | 52D6DA0A1BF000BD002C0205 /* Sources */ = {
546 | isa = PBXSourcesBuildPhase;
547 | buildActionMask = 2147483647;
548 | files = (
549 | D9D9DB8D1E66B2FF0033406B /* Resolve.swift in Sources */,
550 | 04171EEA1E5CDC9500E1C640 /* Mutex.swift in Sources */,
551 | 04171EE71E5CC06E00E1C640 /* Observable.swift in Sources */,
552 | 04171EE41E5CC06E00E1C640 /* Future.swift in Sources */,
553 | 04171EE61E5CC06E00E1C640 /* ExecutionContext.swift in Sources */,
554 | D917F6B11E928638000B1232 /* Future+Operations.swift in Sources */,
555 | 04171EE51E5CC06E00E1C640 /* FutureResult.swift in Sources */,
556 | );
557 | runOnlyForDeploymentPostprocessing = 0;
558 | };
559 | DD7502761C68FCFC006590AF /* Sources */ = {
560 | isa = PBXSourcesBuildPhase;
561 | buildActionMask = 2147483647;
562 | files = (
563 | 04171ED21E5CC05700E1C640 /* EventuallyTests.swift in Sources */,
564 | );
565 | runOnlyForDeploymentPostprocessing = 0;
566 | };
567 | DD7502891C690C7A006590AF /* Sources */ = {
568 | isa = PBXSourcesBuildPhase;
569 | buildActionMask = 2147483647;
570 | files = (
571 | 04171ED31E5CC05800E1C640 /* EventuallyTests.swift in Sources */,
572 | );
573 | runOnlyForDeploymentPostprocessing = 0;
574 | };
575 | /* End PBXSourcesBuildPhase section */
576 |
577 | /* Begin PBXTargetDependency section */
578 | 52D6D9891BEFF229002C0205 /* PBXTargetDependency */ = {
579 | isa = PBXTargetDependency;
580 | target = 52D6D97B1BEFF229002C0205 /* Eventually-iOS */;
581 | targetProxy = 52D6D9881BEFF229002C0205 /* PBXContainerItemProxy */;
582 | };
583 | DD7502811C68FCFC006590AF /* PBXTargetDependency */ = {
584 | isa = PBXTargetDependency;
585 | target = 52D6DA0E1BF000BD002C0205 /* Eventually-macOS */;
586 | targetProxy = DD7502801C68FCFC006590AF /* PBXContainerItemProxy */;
587 | };
588 | DD7502941C690C7A006590AF /* PBXTargetDependency */ = {
589 | isa = PBXTargetDependency;
590 | target = 52D6D9EF1BEFFFBE002C0205 /* Eventually-tvOS */;
591 | targetProxy = DD7502931C690C7A006590AF /* PBXContainerItemProxy */;
592 | };
593 | /* End PBXTargetDependency section */
594 |
595 | /* Begin XCBuildConfiguration section */
596 | 52D6D98E1BEFF229002C0205 /* Debug */ = {
597 | isa = XCBuildConfiguration;
598 | buildSettings = {
599 | ALWAYS_SEARCH_USER_PATHS = NO;
600 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
601 | CLANG_CXX_LIBRARY = "libc++";
602 | CLANG_ENABLE_MODULES = YES;
603 | CLANG_ENABLE_OBJC_ARC = YES;
604 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
605 | CLANG_WARN_BOOL_CONVERSION = YES;
606 | CLANG_WARN_COMMA = YES;
607 | CLANG_WARN_CONSTANT_CONVERSION = YES;
608 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
609 | CLANG_WARN_EMPTY_BODY = YES;
610 | CLANG_WARN_ENUM_CONVERSION = YES;
611 | CLANG_WARN_INFINITE_RECURSION = YES;
612 | CLANG_WARN_INT_CONVERSION = YES;
613 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
614 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
615 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
616 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
617 | CLANG_WARN_STRICT_PROTOTYPES = YES;
618 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
619 | CLANG_WARN_UNREACHABLE_CODE = YES;
620 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
621 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
622 | COPY_PHASE_STRIP = NO;
623 | CURRENT_PROJECT_VERSION = 1;
624 | DEBUG_INFORMATION_FORMAT = dwarf;
625 | ENABLE_STRICT_OBJC_MSGSEND = YES;
626 | ENABLE_TESTABILITY = YES;
627 | GCC_C_LANGUAGE_STANDARD = gnu99;
628 | GCC_DYNAMIC_NO_PIC = NO;
629 | GCC_NO_COMMON_BLOCKS = YES;
630 | GCC_OPTIMIZATION_LEVEL = 0;
631 | GCC_PREPROCESSOR_DEFINITIONS = (
632 | "DEBUG=1",
633 | "$(inherited)",
634 | );
635 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
636 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
637 | GCC_WARN_UNDECLARED_SELECTOR = YES;
638 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
639 | GCC_WARN_UNUSED_FUNCTION = YES;
640 | GCC_WARN_UNUSED_VARIABLE = YES;
641 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
642 | MTL_ENABLE_DEBUG_INFO = YES;
643 | ONLY_ACTIVE_ARCH = YES;
644 | SDKROOT = iphoneos;
645 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
646 | SWIFT_VERSION = 3.0;
647 | TARGETED_DEVICE_FAMILY = "1,2";
648 | VERSIONING_SYSTEM = "apple-generic";
649 | VERSION_INFO_PREFIX = "";
650 | };
651 | name = Debug;
652 | };
653 | 52D6D98F1BEFF229002C0205 /* Release */ = {
654 | isa = XCBuildConfiguration;
655 | buildSettings = {
656 | ALWAYS_SEARCH_USER_PATHS = NO;
657 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
658 | CLANG_CXX_LIBRARY = "libc++";
659 | CLANG_ENABLE_MODULES = YES;
660 | CLANG_ENABLE_OBJC_ARC = YES;
661 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
662 | CLANG_WARN_BOOL_CONVERSION = YES;
663 | CLANG_WARN_COMMA = YES;
664 | CLANG_WARN_CONSTANT_CONVERSION = YES;
665 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
666 | CLANG_WARN_EMPTY_BODY = YES;
667 | CLANG_WARN_ENUM_CONVERSION = YES;
668 | CLANG_WARN_INFINITE_RECURSION = YES;
669 | CLANG_WARN_INT_CONVERSION = YES;
670 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
671 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
672 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
673 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
674 | CLANG_WARN_STRICT_PROTOTYPES = YES;
675 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
676 | CLANG_WARN_UNREACHABLE_CODE = YES;
677 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
678 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
679 | COPY_PHASE_STRIP = NO;
680 | CURRENT_PROJECT_VERSION = 1;
681 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
682 | ENABLE_NS_ASSERTIONS = NO;
683 | ENABLE_STRICT_OBJC_MSGSEND = YES;
684 | GCC_C_LANGUAGE_STANDARD = gnu99;
685 | GCC_NO_COMMON_BLOCKS = YES;
686 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
687 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
688 | GCC_WARN_UNDECLARED_SELECTOR = YES;
689 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
690 | GCC_WARN_UNUSED_FUNCTION = YES;
691 | GCC_WARN_UNUSED_VARIABLE = YES;
692 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
693 | MTL_ENABLE_DEBUG_INFO = NO;
694 | SDKROOT = iphoneos;
695 | SWIFT_VERSION = 3.0;
696 | TARGETED_DEVICE_FAMILY = "1,2";
697 | VALIDATE_PRODUCT = YES;
698 | VERSIONING_SYSTEM = "apple-generic";
699 | VERSION_INFO_PREFIX = "";
700 | };
701 | name = Release;
702 | };
703 | 52D6D9911BEFF229002C0205 /* Debug */ = {
704 | isa = XCBuildConfiguration;
705 | buildSettings = {
706 | APPLICATION_EXTENSION_API_ONLY = YES;
707 | CLANG_ENABLE_MODULES = YES;
708 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
709 | DEFINES_MODULE = YES;
710 | DYLIB_COMPATIBILITY_VERSION = 1;
711 | DYLIB_CURRENT_VERSION = 1;
712 | DYLIB_INSTALL_NAME_BASE = "@rpath";
713 | INFOPLIST_FILE = Configs/Eventually.plist;
714 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
715 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
716 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
717 | ONLY_ACTIVE_ARCH = NO;
718 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-iOS";
719 | PRODUCT_NAME = Eventually;
720 | SKIP_INSTALL = YES;
721 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
722 | SWIFT_VERSION = 4.0;
723 | };
724 | name = Debug;
725 | };
726 | 52D6D9921BEFF229002C0205 /* Release */ = {
727 | isa = XCBuildConfiguration;
728 | buildSettings = {
729 | APPLICATION_EXTENSION_API_ONLY = YES;
730 | CLANG_ENABLE_MODULES = YES;
731 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
732 | DEFINES_MODULE = YES;
733 | DYLIB_COMPATIBILITY_VERSION = 1;
734 | DYLIB_CURRENT_VERSION = 1;
735 | DYLIB_INSTALL_NAME_BASE = "@rpath";
736 | INFOPLIST_FILE = Configs/Eventually.plist;
737 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
738 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
739 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
740 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-iOS";
741 | PRODUCT_NAME = Eventually;
742 | SKIP_INSTALL = YES;
743 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
744 | SWIFT_VERSION = 4.0;
745 | };
746 | name = Release;
747 | };
748 | 52D6D9941BEFF229002C0205 /* Debug */ = {
749 | isa = XCBuildConfiguration;
750 | buildSettings = {
751 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
752 | CLANG_ENABLE_MODULES = YES;
753 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
754 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
755 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-iOS-Tests";
756 | PRODUCT_NAME = "$(TARGET_NAME)";
757 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
758 | SWIFT_VERSION = 4.0;
759 | };
760 | name = Debug;
761 | };
762 | 52D6D9951BEFF229002C0205 /* Release */ = {
763 | isa = XCBuildConfiguration;
764 | buildSettings = {
765 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
766 | CLANG_ENABLE_MODULES = YES;
767 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
768 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
769 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-iOS-Tests";
770 | PRODUCT_NAME = "$(TARGET_NAME)";
771 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
772 | SWIFT_VERSION = 4.0;
773 | };
774 | name = Release;
775 | };
776 | 52D6D9E81BEFFF6E002C0205 /* Debug */ = {
777 | isa = XCBuildConfiguration;
778 | buildSettings = {
779 | APPLICATION_EXTENSION_API_ONLY = YES;
780 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
781 | DEFINES_MODULE = YES;
782 | DYLIB_COMPATIBILITY_VERSION = 1;
783 | DYLIB_CURRENT_VERSION = 1;
784 | DYLIB_INSTALL_NAME_BASE = "@rpath";
785 | INFOPLIST_FILE = Configs/Eventually.plist;
786 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
787 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
788 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-watchOS";
789 | PRODUCT_NAME = Eventually;
790 | SDKROOT = watchos;
791 | SKIP_INSTALL = YES;
792 | SWIFT_VERSION = 3.0;
793 | TARGETED_DEVICE_FAMILY = 4;
794 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
795 | };
796 | name = Debug;
797 | };
798 | 52D6D9E91BEFFF6E002C0205 /* Release */ = {
799 | isa = XCBuildConfiguration;
800 | buildSettings = {
801 | APPLICATION_EXTENSION_API_ONLY = YES;
802 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
803 | DEFINES_MODULE = YES;
804 | DYLIB_COMPATIBILITY_VERSION = 1;
805 | DYLIB_CURRENT_VERSION = 1;
806 | DYLIB_INSTALL_NAME_BASE = "@rpath";
807 | INFOPLIST_FILE = Configs/Eventually.plist;
808 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
809 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
810 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-watchOS";
811 | PRODUCT_NAME = Eventually;
812 | SDKROOT = watchos;
813 | SKIP_INSTALL = YES;
814 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
815 | SWIFT_VERSION = 3.0;
816 | TARGETED_DEVICE_FAMILY = 4;
817 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
818 | };
819 | name = Release;
820 | };
821 | 52D6DA021BEFFFBE002C0205 /* Debug */ = {
822 | isa = XCBuildConfiguration;
823 | buildSettings = {
824 | APPLICATION_EXTENSION_API_ONLY = YES;
825 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
826 | DEFINES_MODULE = YES;
827 | DYLIB_COMPATIBILITY_VERSION = 1;
828 | DYLIB_CURRENT_VERSION = 1;
829 | DYLIB_INSTALL_NAME_BASE = "@rpath";
830 | INFOPLIST_FILE = Configs/Eventually.plist;
831 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
832 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
833 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-tvOS";
834 | PRODUCT_NAME = Eventually;
835 | SDKROOT = appletvos;
836 | SKIP_INSTALL = YES;
837 | SWIFT_VERSION = 3.0;
838 | TARGETED_DEVICE_FAMILY = 3;
839 | TVOS_DEPLOYMENT_TARGET = 9.0;
840 | };
841 | name = Debug;
842 | };
843 | 52D6DA031BEFFFBE002C0205 /* Release */ = {
844 | isa = XCBuildConfiguration;
845 | buildSettings = {
846 | APPLICATION_EXTENSION_API_ONLY = YES;
847 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
848 | DEFINES_MODULE = YES;
849 | DYLIB_COMPATIBILITY_VERSION = 1;
850 | DYLIB_CURRENT_VERSION = 1;
851 | DYLIB_INSTALL_NAME_BASE = "@rpath";
852 | INFOPLIST_FILE = Configs/Eventually.plist;
853 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
854 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
855 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-tvOS";
856 | PRODUCT_NAME = Eventually;
857 | SDKROOT = appletvos;
858 | SKIP_INSTALL = YES;
859 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
860 | SWIFT_VERSION = 3.0;
861 | TARGETED_DEVICE_FAMILY = 3;
862 | TVOS_DEPLOYMENT_TARGET = 9.0;
863 | };
864 | name = Release;
865 | };
866 | 52D6DA211BF000BD002C0205 /* Debug */ = {
867 | isa = XCBuildConfiguration;
868 | buildSettings = {
869 | APPLICATION_EXTENSION_API_ONLY = YES;
870 | CODE_SIGN_IDENTITY = "-";
871 | COMBINE_HIDPI_IMAGES = YES;
872 | DEFINES_MODULE = YES;
873 | DYLIB_COMPATIBILITY_VERSION = 1;
874 | DYLIB_CURRENT_VERSION = 1;
875 | DYLIB_INSTALL_NAME_BASE = "@rpath";
876 | FRAMEWORK_VERSION = A;
877 | INFOPLIST_FILE = Configs/Eventually.plist;
878 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
879 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
880 | MACOSX_DEPLOYMENT_TARGET = 10.10;
881 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-macOS";
882 | PRODUCT_NAME = Eventually;
883 | SDKROOT = macosx;
884 | SKIP_INSTALL = YES;
885 | SWIFT_VERSION = 3.0;
886 | };
887 | name = Debug;
888 | };
889 | 52D6DA221BF000BD002C0205 /* Release */ = {
890 | isa = XCBuildConfiguration;
891 | buildSettings = {
892 | APPLICATION_EXTENSION_API_ONLY = YES;
893 | CODE_SIGN_IDENTITY = "-";
894 | COMBINE_HIDPI_IMAGES = YES;
895 | DEFINES_MODULE = YES;
896 | DYLIB_COMPATIBILITY_VERSION = 1;
897 | DYLIB_CURRENT_VERSION = 1;
898 | DYLIB_INSTALL_NAME_BASE = "@rpath";
899 | FRAMEWORK_VERSION = A;
900 | INFOPLIST_FILE = Configs/Eventually.plist;
901 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
902 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
903 | MACOSX_DEPLOYMENT_TARGET = 10.10;
904 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-macOS";
905 | PRODUCT_NAME = Eventually;
906 | SDKROOT = macosx;
907 | SKIP_INSTALL = YES;
908 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
909 | SWIFT_VERSION = 3.0;
910 | };
911 | name = Release;
912 | };
913 | DD7502831C68FCFC006590AF /* Debug */ = {
914 | isa = XCBuildConfiguration;
915 | buildSettings = {
916 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
917 | CODE_SIGN_IDENTITY = "-";
918 | COMBINE_HIDPI_IMAGES = YES;
919 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
920 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
921 | MACOSX_DEPLOYMENT_TARGET = 10.11;
922 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-macOS-Tests";
923 | PRODUCT_NAME = "$(TARGET_NAME)";
924 | SDKROOT = macosx;
925 | SWIFT_VERSION = 3.0;
926 | };
927 | name = Debug;
928 | };
929 | DD7502841C68FCFC006590AF /* Release */ = {
930 | isa = XCBuildConfiguration;
931 | buildSettings = {
932 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
933 | CODE_SIGN_IDENTITY = "-";
934 | COMBINE_HIDPI_IMAGES = YES;
935 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
936 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
937 | MACOSX_DEPLOYMENT_TARGET = 10.11;
938 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-macOS-Tests";
939 | PRODUCT_NAME = "$(TARGET_NAME)";
940 | SDKROOT = macosx;
941 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
942 | SWIFT_VERSION = 3.0;
943 | };
944 | name = Release;
945 | };
946 | DD7502961C690C7A006590AF /* Debug */ = {
947 | isa = XCBuildConfiguration;
948 | buildSettings = {
949 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
950 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
951 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
952 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-tvOS-Tests";
953 | PRODUCT_NAME = "$(TARGET_NAME)";
954 | SDKROOT = appletvos;
955 | SWIFT_VERSION = 3.0;
956 | TVOS_DEPLOYMENT_TARGET = 9.1;
957 | };
958 | name = Debug;
959 | };
960 | DD7502971C690C7A006590AF /* Release */ = {
961 | isa = XCBuildConfiguration;
962 | buildSettings = {
963 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
964 | INFOPLIST_FILE = Configs/EventuallyTests.plist;
965 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
966 | PRODUCT_BUNDLE_IDENTIFIER = "com.Eventually.Eventually-tvOS-Tests";
967 | PRODUCT_NAME = "$(TARGET_NAME)";
968 | SDKROOT = appletvos;
969 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
970 | SWIFT_VERSION = 3.0;
971 | TVOS_DEPLOYMENT_TARGET = 9.1;
972 | };
973 | name = Release;
974 | };
975 | /* End XCBuildConfiguration section */
976 |
977 | /* Begin XCConfigurationList section */
978 | 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "Eventually" */ = {
979 | isa = XCConfigurationList;
980 | buildConfigurations = (
981 | 52D6D98E1BEFF229002C0205 /* Debug */,
982 | 52D6D98F1BEFF229002C0205 /* Release */,
983 | );
984 | defaultConfigurationIsVisible = 0;
985 | defaultConfigurationName = Release;
986 | };
987 | 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Eventually-iOS" */ = {
988 | isa = XCConfigurationList;
989 | buildConfigurations = (
990 | 52D6D9911BEFF229002C0205 /* Debug */,
991 | 52D6D9921BEFF229002C0205 /* Release */,
992 | );
993 | defaultConfigurationIsVisible = 0;
994 | defaultConfigurationName = Release;
995 | };
996 | 52D6D9931BEFF229002C0205 /* Build configuration list for PBXNativeTarget "Eventually-iOS Tests" */ = {
997 | isa = XCConfigurationList;
998 | buildConfigurations = (
999 | 52D6D9941BEFF229002C0205 /* Debug */,
1000 | 52D6D9951BEFF229002C0205 /* Release */,
1001 | );
1002 | defaultConfigurationIsVisible = 0;
1003 | defaultConfigurationName = Release;
1004 | };
1005 | 52D6D9E71BEFFF6E002C0205 /* Build configuration list for PBXNativeTarget "Eventually-watchOS" */ = {
1006 | isa = XCConfigurationList;
1007 | buildConfigurations = (
1008 | 52D6D9E81BEFFF6E002C0205 /* Debug */,
1009 | 52D6D9E91BEFFF6E002C0205 /* Release */,
1010 | );
1011 | defaultConfigurationIsVisible = 0;
1012 | defaultConfigurationName = Release;
1013 | };
1014 | 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "Eventually-tvOS" */ = {
1015 | isa = XCConfigurationList;
1016 | buildConfigurations = (
1017 | 52D6DA021BEFFFBE002C0205 /* Debug */,
1018 | 52D6DA031BEFFFBE002C0205 /* Release */,
1019 | );
1020 | defaultConfigurationIsVisible = 0;
1021 | defaultConfigurationName = Release;
1022 | };
1023 | 52D6DA201BF000BD002C0205 /* Build configuration list for PBXNativeTarget "Eventually-macOS" */ = {
1024 | isa = XCConfigurationList;
1025 | buildConfigurations = (
1026 | 52D6DA211BF000BD002C0205 /* Debug */,
1027 | 52D6DA221BF000BD002C0205 /* Release */,
1028 | );
1029 | defaultConfigurationIsVisible = 0;
1030 | defaultConfigurationName = Release;
1031 | };
1032 | DD7502821C68FCFC006590AF /* Build configuration list for PBXNativeTarget "Eventually-macOS Tests" */ = {
1033 | isa = XCConfigurationList;
1034 | buildConfigurations = (
1035 | DD7502831C68FCFC006590AF /* Debug */,
1036 | DD7502841C68FCFC006590AF /* Release */,
1037 | );
1038 | defaultConfigurationIsVisible = 0;
1039 | defaultConfigurationName = Release;
1040 | };
1041 | DD7502951C690C7A006590AF /* Build configuration list for PBXNativeTarget "Eventually-tvOS Tests" */ = {
1042 | isa = XCConfigurationList;
1043 | buildConfigurations = (
1044 | DD7502961C690C7A006590AF /* Debug */,
1045 | DD7502971C690C7A006590AF /* Release */,
1046 | );
1047 | defaultConfigurationIsVisible = 0;
1048 | defaultConfigurationName = Release;
1049 | };
1050 | /* End XCConfigurationList section */
1051 | };
1052 | rootObject = 52D6D9731BEFF229002C0205 /* Project object */;
1053 | }
1054 |
--------------------------------------------------------------------------------