├── Configurations
├── Shared
├── Version.xcconfig
├── BoltsSwift-iOS.xcconfig
├── BoltsSwift-tvOS.xcconfig
├── BoltsSwift-macOS.xcconfig
├── BoltsSwift-watchOS.xcconfig
├── BoltsSwiftTests-iOS.xcconfig
├── BoltsSwiftTests-tvOS.xcconfig
├── BoltsSwiftTests-macOS.xcconfig
├── BoltsSwiftTests-Shared.xcconfig
└── BoltsSwift-Shared.xcconfig
├── .gitmodules
├── .github_changelog_generator
├── .codecov.yml
├── .swiftlint.yml
├── BoltsSwift.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── BoltsSwift.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ ├── BoltsSwift-watchOS.xcscheme
│ │ ├── BoltsSwift-iOS.xcscheme
│ │ ├── BoltsSwift-tvOS.xcscheme
│ │ └── BoltsSwift-macOS.xcscheme
└── project.pbxproj
├── CODE_OF_CONDUCT.md
├── .gitignore
├── Tests
├── XCTestCase+TestName.swift
├── Info.plist
├── TaskCompletionSourceTests.swift
├── ExecutorTests.swift
└── TaskTests.swift
├── Package.swift
├── Bolts-Swift.podspec
├── Sources
├── Info.plist
└── BoltsSwift
│ ├── Errors.swift
│ ├── Task+Delay.swift
│ ├── Task+WhenAny.swift
│ ├── TaskCompletionSource.swift
│ ├── Task+WhenAll.swift
│ ├── Executor.swift
│ ├── Task+ContinueWith.swift
│ └── Task.swift
├── CONTRIBUTING.md
├── LICENSE
├── PATENTS
├── .travis.yml
├── CHANGELOG.md
└── README.md
/Configurations/Shared:
--------------------------------------------------------------------------------
1 | ../Vendor/xctoolchain/Configurations/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Vendor/xctoolchain"]
2 | path = Vendor/xctoolchain
3 | url = https://github.com/nlutsenko/xctoolchain.git
4 |
--------------------------------------------------------------------------------
/.github_changelog_generator:
--------------------------------------------------------------------------------
1 | issues=true
2 | issues-wo-labels=false
3 | exclude_labels=duplicate,question,wontfix,discussion,needs more info,backend,cocoapods,off topic,product usage,invalid
4 |
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | ignore:
3 | - Tests/.*
4 | status:
5 | patch: false
6 | changes: false
7 | project:
8 | default:
9 | target: 75
10 | comment: false
11 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | line_length: 140
2 | file_length: 1000
3 | type_body_length: 500
4 | opt_in_rules:
5 | - empty_count
6 | disabled_rules:
7 | - cyclomatic_complexity
8 | - variable_name
9 | - no_fallthrough_only
10 |
--------------------------------------------------------------------------------
/BoltsSwift.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 | Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
--------------------------------------------------------------------------------
/BoltsSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Configurations/Version.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | BOLTS_SWIFT_VERSION = 1.5.0
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## OS X
2 | .DS_Store
3 |
4 | ## Build generated
5 | .build/
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Dependency Managers
31 | Pods/
32 | Carthage/Build
33 |
34 | ## AppCode
35 | .idea/
36 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwift-iOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/iOS.xcconfig"
11 |
12 | #include "BoltsSwift-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.ios
15 |
16 | IPHONEOS_DEPLOYMENT_TARGET = 11.0
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwift-tvOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/tvOS.xcconfig"
11 |
12 | #include "BoltsSwift-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.tvos
15 |
16 | TVOS_DEPLOYMENT_TARGET = 11.0
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwift-macOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/macOS.xcconfig"
11 |
12 | #include "BoltsSwift-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.macos
15 |
16 | MACOSX_DEPLOYMENT_TARGET = 10.13
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwift-watchOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/watchOS.xcconfig"
11 |
12 | #include "BoltsSwift-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.watchos
15 |
16 | WATCHOS_DEPLOYMENT_TARGET = 4.0
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwiftTests-iOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/iOS.xcconfig"
11 |
12 | #include "BoltsSwiftTests-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.ios.tests
15 |
16 | IPHONEOS_DEPLOYMENT_TARGET = 11.0
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwiftTests-tvOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/tvOS.xcconfig"
11 |
12 | #include "BoltsSwiftTests-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.tvos.tests
15 |
16 | TVOS_DEPLOYMENT_TARGET = 11.0
17 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwiftTests-macOS.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Platform/macOS.xcconfig"
11 |
12 | #include "BoltsSwiftTests-Shared.xcconfig"
13 |
14 | PRODUCT_BUNDLE_IDENTIFIER = com.bolts.swift.macos.tests
15 |
16 | MACOSX_DEPLOYMENT_TARGET = 10.13
17 |
--------------------------------------------------------------------------------
/Tests/XCTestCase+TestName.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import XCTest
11 |
12 | extension XCTestCase {
13 | /**
14 | Waits for all test expectations with a default timeout.
15 | */
16 | func waitForTestExpectations() {
17 | waitForExpectations(timeout: 10, handler: nil)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwiftTests-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Product/LogicTests.xcconfig"
11 |
12 | //
13 | // This file contains shared configuration for all "Tests" targets.
14 | // Only shared configurations belong here.
15 | //
16 |
17 | PRODUCT_NAME = BoltsSwiftTests
18 |
19 | SWIFT_VERSION = 5.0
20 |
21 | INFOPLIST_FILE = $(SRCROOT)/Tests/Info.plist
22 |
--------------------------------------------------------------------------------
/Configurations/BoltsSwift-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2016, Facebook, Inc.
3 | // All rights reserved.
4 | //
5 | // This source code is licensed under the BSD-style license found in the
6 | // LICENSE file in the root directory of this source tree. An additional grant
7 | // of patent rights can be found in the PATENTS file in the same directory.
8 | //
9 |
10 | #include "Shared/Product/DynamicFramework.xcconfig"
11 |
12 | #include "Version.xcconfig"
13 |
14 | //
15 | // This file contains shared configuration for all "Framework" targets.
16 | // Only shared configurations belong here.
17 | //
18 |
19 | PRODUCT_NAME = BoltsSwift
20 |
21 | SWIFT_VERSION = 5.0
22 |
23 | INFOPLIST_FILE = $(SRCROOT)/Sources/Info.plist
24 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.0
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "BoltsSwift",
7 | platforms: [.macOS(.v10_10),
8 | .iOS(.v8),
9 | .tvOS(.v9),
10 | .watchOS(.v3)],
11 | products: [
12 | .library(
13 | name: "BoltsSwift",
14 | targets: ["BoltsSwift"])
15 | ],
16 | targets: [
17 | .target(
18 | name: "BoltsSwift",
19 | path: "Sources/BoltsSwift"),
20 | .testTarget(
21 | name: "BoltsSwiftTests",
22 | dependencies: ["BoltsSwift"],
23 | path: "Tests")
24 | ],
25 | swiftLanguageVersions: [.v4,
26 | .v4_2,
27 | .v5]
28 | )
29 |
--------------------------------------------------------------------------------
/Tests/Info.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 |
--------------------------------------------------------------------------------
/Bolts-Swift.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'Bolts-Swift'
3 | s.version = '1.5.0'
4 | s.license = { :type => 'BSD' }
5 | s.summary = 'Bolts is a collection of low-level libraries designed to make developing mobile apps easier.'
6 | s.homepage = 'https://github.com/BoltsFramework'
7 | s.authors = { 'Nikita Lutsenko' => 'nlutsenko@me.com' }
8 |
9 | s.source = { :git => 'https://github.com/BoltsFramework/Bolts-Swift.git', :tag => s.version.to_s }
10 |
11 | s.requires_arc = true
12 |
13 | s.swift_version = '5.0'
14 |
15 | s.ios.deployment_target = '8.0'
16 | s.osx.deployment_target = '10.10'
17 | s.tvos.deployment_target = '9.0'
18 | s.watchos.deployment_target = '2.0'
19 |
20 | s.source_files = 'Sources/BoltsSwift/*.swift'
21 | s.module_name = 'BoltsSwift'
22 | end
23 |
--------------------------------------------------------------------------------
/Sources/Info.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 | $(BOLTS_SWIFT_VERSION)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(BOLTS_SWIFT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Errors.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | /**
13 | An error type that contains one or more underlying errors.
14 | */
15 | public struct AggregateError: Error {
16 | /// An array of errors that are aggregated into this one.
17 | public let errors: [Error]
18 |
19 | init(errors: [Error]) {
20 | self.errors = errors
21 | }
22 | }
23 |
24 | /**
25 | An error type that indicates that the task was cancelled.
26 |
27 | Return or throw this from a continuation closure to propagate to the `task.cancelled` property.
28 | */
29 | public struct CancelledError: Error {
30 | /**
31 | Initializes a Cancelled Error.
32 | */
33 | public init() { }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Task+Delay.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | //--------------------------------------
13 | // MARK: - Task with Delay
14 | //--------------------------------------
15 |
16 | extension Task {
17 | /**
18 | Creates a task that will complete after the given delay.
19 |
20 | - parameter delay: The delay for the task to completes.
21 |
22 | - returns: A task that will complete after the given delay.
23 | */
24 | public class func withDelay(_ delay: TimeInterval) -> Task {
25 | let taskCompletionSource = TaskCompletionSource()
26 | let time = DispatchTime.now() + delay
27 | DispatchQueue.global(qos: .default).asyncAfter(deadline: time) {
28 | taskCompletionSource.trySet(result: ())
29 | }
30 | return taskCompletionSource.task
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Bolts-Swift
2 | We want to make contributing to this project as easy and transparent as
3 | possible.
4 |
5 | ## Pull Requests
6 | We actively welcome your pull requests.
7 |
8 | 1. Fork the repo and create your branch from `master`.
9 | 2. If you've added code that should be tested, add tests.
10 | 3. If you've changed APIs, update the documentation.
11 | 4. Ensure the test suite passes.
12 | 5. Make sure your code lints.
13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA").
14 |
15 | ## Contributor License Agreement ("CLA")
16 | In order to accept your pull request, we need you to submit a CLA. You only need
17 | to do this once to work on any of Facebook's open source projects.
18 |
19 | Complete your CLA here:
20 |
21 | ## Issues
22 | We use GitHub issues to track public bugs. Please ensure your description is
23 | clear and has sufficient instructions to be able to reproduce the issue.
24 |
25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
26 | disclosure of security bugs. In those cases, please go through the process
27 | outlined on that page and do not file a public issue.
28 |
29 | ## Coding Style
30 | * Most importantly, match the existing code style as much as possible.
31 | * Try to keep lines under 140 characters, if possible.
32 |
33 | ## License
34 | By contributing to Bolts-Swift, you agree that your contributions will be licensed
35 | under its BSD license.
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD License
2 |
3 | For Bolts-Swift software
4 |
5 | Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification,
8 | are permitted provided that the following conditions are met:
9 |
10 | * Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | this list of conditions and the following disclaimer in the documentation
15 | and/or other materials provided with the distribution.
16 |
17 | * Neither the name Facebook nor the names of its contributors may be used to
18 | endorse or promote products derived from this software without specific
19 | prior written permission.
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/PATENTS:
--------------------------------------------------------------------------------
1 | Additional Grant of Patent Rights Version 2
2 |
3 | "Software" means the Bolts-Swift software distributed by Facebook, Inc.
4 |
5 | Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software
6 | ("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
7 | (subject to the termination provision below) license under any Necessary
8 | Claims, to make, have made, use, sell, offer to sell, import, and otherwise
9 | transfer the Software. For avoidance of doubt, no license is granted under
10 | Facebook’s rights in any patent claims that are infringed by (i) modifications
11 | to the Software made by you or any third party or (ii) the Software in
12 | combination with any software or other technology.
13 |
14 | The license granted hereunder will terminate, automatically and without notice,
15 | if you (or any of your subsidiaries, corporate affiliates or agents) initiate
16 | directly or indirectly, or take a direct financial interest in, any Patent
17 | Assertion: (i) against Facebook or any of its subsidiaries or corporate
18 | affiliates, (ii) against any party if such Patent Assertion arises in whole or
19 | in part from any software, technology, product or service of Facebook or any of
20 | its subsidiaries or corporate affiliates, or (iii) against any party relating
21 | to the Software. Notwithstanding the foregoing, if Facebook or any of its
22 | subsidiaries or corporate affiliates files a lawsuit alleging patent
23 | infringement against you in the first instance, and you respond by filing a
24 | patent infringement counterclaim in that lawsuit against that party that is
25 | unrelated to the Software, the license granted hereunder will not terminate
26 | under section (i) of this paragraph due to such counterclaim.
27 |
28 | A "Necessary Claim" is a claim of a patent owned by Facebook that is
29 | necessarily infringed by the Software standing alone.
30 |
31 | A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
32 | or contributory infringement or inducement to infringe any patent, including a
33 | cross-claim or counterclaim.
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Task+WhenAny.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | //--------------------------------------
13 | // MARK: - WhenAny
14 | //--------------------------------------
15 |
16 | extension Task {
17 |
18 | /**
19 | Creates a task that will complete when any of the input tasks have completed.
20 |
21 | The returned task will complete when any of the supplied tasks have completed.
22 | This is true even if the first task to complete ended in the canceled or faulted state.
23 |
24 | - parameter tasks: Array of tasks to wait on for completion.
25 |
26 | - returns: A new task that will complete when any of the `tasks` are completed.
27 | */
28 | public class func whenAny(_ tasks: [Task]) -> Task {
29 | if tasks.isEmpty {
30 | return Task.emptyTask()
31 | }
32 | let taskCompletionSource = TaskCompletionSource()
33 | for task in tasks {
34 | // Do not continue anything if we completed the task, because we fulfilled our job here.
35 | if taskCompletionSource.task.completed {
36 | break
37 | }
38 | task.continueWith { _ in
39 | taskCompletionSource.trySet(result: ())
40 | }
41 | }
42 | return taskCompletionSource.task
43 | }
44 |
45 | /**
46 | Creates a task that will complete when any of the input tasks have completed.
47 |
48 | The returned task will complete when any of the supplied tasks have completed.
49 | This is true even if the first task to complete ended in the canceled or faulted state.
50 |
51 | - parameter tasks: Zeror or more tasks to wait on for completion.
52 |
53 | - returns: A new task that will complete when any of the `tasks` are completed.
54 | */
55 | public class func whenAny(_ tasks: Task...) -> Task {
56 | return whenAny(tasks)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/xcshareddata/xcschemes/BoltsSwift-watchOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
52 |
53 |
59 |
60 |
66 |
67 |
68 |
69 |
71 |
72 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | branches:
2 | only:
3 | - master
4 | language: objective-c
5 | os: osx
6 | cache:
7 | - cocoapods
8 | matrix:
9 | include:
10 | - osx_image: xcode9
11 | env: TEST_TYPE=iOS SWIFT_VERSION=4.0 DESTINATION='platform=iOS Simulator,name=iPhone 4s,OS=8.1'
12 | - osx_image: xcode10
13 | env: TEST_TYPE=iOS SWIFT_VERSION=4.2 DESTINATION='platform=iOS Simulator,name=iPhone X,OS=11.1'
14 | - osx_image: xcode11
15 | env: TEST_TYPE=iOS SWIFT_VERSION=5.0 DESTINATION='platform=iOS Simulator,name=iPhone 11 Pro,OS=13.0'
16 | - osx_image: xcode11
17 | env: TEST_TYPE=macOS SWIFT_VERSION=5.0
18 | - osx_image: xcode11
19 | env: TEST_TYPE=tvOS SWIFT_VERSION=5.0
20 | - osx_image: xcode11
21 | env: TEST_TYPE=SwiftPM
22 | - osx_image: xcode11
23 | env: TEST_TYPE=Lint
24 | - osx_image: xcode11
25 | env: TEST_TYPE=Distribution
26 | before_install:
27 | - |
28 | if [ "$TEST_TYPE" = Lint ] || [ "$TEST_TYPE" = Distribution ]; then
29 | brew update
30 | fi
31 | install:
32 | - |
33 | if [ "$TEST_TYPE" = iOS ] || [ "$TEST_TYPE" = macOS ] || [ "$TEST_TYPE" = tvOS ]; then
34 | gem install xcpretty --no-document
35 | elif [ "$TEST_TYPE" = Lint ]; then
36 | brew install swiftlint || brew upgrade swiftlint
37 | elif [ "$TEST_TYPE" = Distribution ]; then
38 | gem install cocoapods --pre --quiet --no-document
39 | brew install carthage || brew upgrade carthage
40 | fi
41 | script:
42 | - |
43 | [ ! -z "$SWIFT_VERSION" ] && sed -i '' -e "s/^SWIFT_VERSION *=.*/SWIFT_VERSION = $SWIFT_VERSION/g" Configurations/*.xcconfig
44 | if [ "$TEST_TYPE" = iOS ]; then
45 | set -o pipefail
46 | xcodebuild test -project BoltsSwift.xcodeproj -sdk iphonesimulator -scheme BoltsSwift-iOS -configuration Debug -destination "$DESTINATION" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
47 | xcodebuild test -project BoltsSwift.xcodeproj -sdk iphonesimulator -scheme BoltsSwift-iOS -configuration Release -destination "$DESTINATION" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
48 | elif [ "$TEST_TYPE" = macOS ]; then
49 | set -o pipefail
50 | xcodebuild test -project BoltsSwift.xcodeproj -sdk macosx -scheme BoltsSwift-macOS -configuration Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
51 | xcodebuild test -project BoltsSwift.xcodeproj -sdk macosx -scheme BoltsSwift-macOS -configuration Release GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
52 | elif [ "$TEST_TYPE" = tvOS ]; then
53 | set -o pipefail
54 | xcodebuild test -project BoltsSwift.xcodeproj -sdk appletvsimulator -scheme BoltsSwift-tvOS -destination "platform=tvOS Simulator,name=Apple TV" -configuration Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
55 | xcodebuild test -project BoltsSwift.xcodeproj -sdk appletvsimulator -scheme BoltsSwift-tvOS -destination "platform=tvOS Simulator,name=Apple TV" -configuration Release GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
56 | elif [ "$TEST_TYPE" = SwiftPM ]; then
57 | swift test -v
58 | elif [ "$TEST_TYPE" = Lint ]; then
59 | swiftlint lint
60 | elif [ "$TEST_TYPE" = Distribution ]; then
61 | pod lib lint Bolts-Swift.podspec
62 | carthage build --no-skip-current
63 | fi
64 | after_success:
65 | - |
66 | if [ "$TEST_TYPE" = iOS ] || [ "$TEST_TYPE" = macOS ] || [ "$TEST_TYPE" = tvOS ]; then
67 | bash <(curl -s https://codecov.io/bash)
68 | fi
69 |
--------------------------------------------------------------------------------
/Tests/TaskCompletionSourceTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import XCTest
11 | import BoltsSwift
12 |
13 | class TaskCompletionSourceTests: XCTestCase {
14 |
15 | func testInit() {
16 | let tcs = TaskCompletionSource()
17 | let task = tcs.task
18 |
19 | XCTAssertFalse(task.completed)
20 | XCTAssertFalse(task.faulted)
21 | XCTAssertFalse(task.cancelled)
22 | XCTAssertNil(task.result)
23 | XCTAssertNil(task.error)
24 | }
25 |
26 | func testSetResult() {
27 | let tcs = TaskCompletionSource()
28 | let task = tcs.task
29 |
30 | tcs.set(result: name)
31 |
32 | XCTAssertTrue(task.completed)
33 | XCTAssertNotNil(task.result)
34 | XCTAssertEqual(task.result, name)
35 | }
36 |
37 | func testSetError() {
38 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
39 | let tcs = TaskCompletionSource()
40 | let task = tcs.task
41 |
42 | tcs.set(error: error)
43 |
44 | XCTAssertTrue(task.completed)
45 | XCTAssertTrue(task.faulted)
46 | XCTAssertNotNil(task.error)
47 | XCTAssertEqual(task.error as NSError?, error)
48 | }
49 |
50 | func testCancel() {
51 | let tcs = TaskCompletionSource()
52 | let task = tcs.task
53 |
54 | tcs.cancel()
55 |
56 | XCTAssertTrue(task.completed)
57 | XCTAssertTrue(task.cancelled)
58 | }
59 |
60 | func testTrySetResultReturningTrue() {
61 | let sut = TaskCompletionSource()
62 | let task = sut.task
63 |
64 | let success = sut.trySet(result: name)
65 |
66 | XCTAssertTrue(success)
67 | XCTAssertTrue(task.completed)
68 | XCTAssertNotNil(task.result)
69 | XCTAssertEqual(task.result, name)
70 | }
71 |
72 | func testTrySetErrorReturningTrue() {
73 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
74 | let sut = TaskCompletionSource()
75 | let task = sut.task
76 |
77 | let success = sut.trySet(error: error)
78 |
79 | XCTAssertTrue(success)
80 | XCTAssertTrue(task.completed)
81 | XCTAssertTrue(task.faulted)
82 | XCTAssertNotNil(task.error)
83 | XCTAssertEqual(task.error as NSError?, error)
84 | }
85 |
86 | func testTryCancelReturningTrue() {
87 | let sut = TaskCompletionSource()
88 | let task = sut.task
89 |
90 | let success = sut.tryCancel()
91 |
92 | XCTAssertTrue(success)
93 | XCTAssertTrue(task.completed)
94 | XCTAssertTrue(task.cancelled)
95 | }
96 |
97 | func testTrySetResultReturningFalse() {
98 | let sut = TaskCompletionSource()
99 | sut.set(result: name)
100 |
101 | let success = sut.trySet(result: name)
102 |
103 | XCTAssertFalse(success)
104 | }
105 |
106 | func testTrySetErrorReturningFalse() {
107 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
108 | let sut = TaskCompletionSource()
109 | sut.set(result: name)
110 |
111 | let success = sut.trySet(error: error)
112 |
113 | XCTAssertFalse(success)
114 | }
115 |
116 | func testTryCancelReturningFalse() {
117 | let sut = TaskCompletionSource()
118 | sut.set(result: name)
119 | let success = sut.tryCancel()
120 | XCTAssertFalse(success)
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/xcshareddata/xcschemes/BoltsSwift-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/xcshareddata/xcschemes/BoltsSwift-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/TaskCompletionSource.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | /// A `TaskCompletionSource` represents the producer side of a `Task`,
13 | /// providing access to the consumer side through the `task` property.
14 | /// As a producer, it can complete the underlying task by either by setting its result, error or cancelling it.
15 | ///
16 | /// For example, this is how you could use a task completion source
17 | /// to provide a task that asynchronously reads data from disk:
18 | ///
19 | /// func dataFromPath(path: String) -> Task {
20 | /// let tcs = TaskCompletionSource()
21 | /// DispatchQueue.global(qos: .default).async {
22 | /// if let data = NSData(contentsOfFile: path) {
23 | /// tcs.set(result: data)
24 | /// } else {
25 | /// tcs.set(error: NSError(domain: "com.example", code: 0, userInfo: nil))
26 | /// }
27 | /// }
28 | /// return tcs.task
29 | /// }
30 | public class TaskCompletionSource {
31 |
32 | /// The underlying task.
33 | public let task = Task()
34 |
35 | /// Creates a task completion source with a pending task.
36 | public init() {}
37 |
38 | //--------------------------------------
39 | // MARK: - Change Task State
40 | //--------------------------------------
41 |
42 | /**
43 | Completes the task with the given result.
44 |
45 | Throws an exception if the task is already completed.
46 |
47 | - parameter result: The task result.
48 | */
49 | public func set(result: TResult) {
50 | guard task.trySet(state: .success(result)) else {
51 | preconditionFailure("Can not set the result on a completed task.")
52 | }
53 | }
54 |
55 | /**
56 | Completes the task with the given error.
57 |
58 | Throws an exception if the task is already completed.
59 |
60 | - parameter error: The task error.
61 | */
62 | public func set(error: Error) {
63 | guard task.trySet(state: .error(error)) else {
64 | preconditionFailure("Can not set error on a completed task.")
65 | }
66 | }
67 |
68 | /**
69 | Cancels the task.
70 |
71 | Throws an exception if the task is already completed.
72 | */
73 | public func cancel() {
74 | guard task.trySet(state: .cancelled) else {
75 | preconditionFailure("Can not cancel a completed task.")
76 | }
77 | }
78 |
79 | /**
80 | Tries to complete the task with the given result.
81 |
82 | - parameter result: The task result.
83 | - returns: `true` if the result was set, `false` otherwise.
84 | */
85 | @discardableResult
86 | public func trySet(result: TResult) -> Bool {
87 | return task.trySet(state: .success(result))
88 | }
89 |
90 | /**
91 | Tries to completes the task with the given error.
92 |
93 | - parameter error: The task error.
94 | - returns: `true` if the error was set, `false` otherwise.
95 | */
96 | @discardableResult
97 | public func trySet(error: Error) -> Bool {
98 | return task.trySet(state: .error(error))
99 | }
100 |
101 | /**
102 | Cancels the task.
103 |
104 | - returns: `true` if the task was completed, `false` otherwise.
105 | */
106 | @discardableResult
107 | public func tryCancel() -> Bool {
108 | return task.trySet(state: .cancelled)
109 | }
110 |
111 | //--------------------------------------
112 | // MARK: - Change Task State (internal)
113 | //--------------------------------------
114 |
115 | func setState(_ state: TaskState) {
116 | guard task.trySet(state: state) else {
117 | preconditionFailure("Can not complete a completed task.")
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Task+WhenAll.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | //--------------------------------------
13 | // MARK: - WhenAll
14 | //--------------------------------------
15 |
16 | extension Task {
17 |
18 | /**
19 | Creates a task that will be completed after all of the input tasks have completed.
20 |
21 | - parameter tasks: Array tasks to wait on for completion.
22 |
23 | - returns: A new task that will complete after all `tasks` are completed.
24 | */
25 | public class func whenAll(_ tasks: [Task]) -> Task {
26 | if tasks.isEmpty {
27 | return Task.emptyTask()
28 | }
29 |
30 | var tasksCount: Int32 = Int32(tasks.count)
31 | var cancelledCount: Int32 = 0
32 | var errorCount: Int32 = 0
33 |
34 | let tcs = TaskCompletionSource()
35 | tasks.forEach {
36 | $0.continueWith { task -> Void in
37 | if task.cancelled {
38 | OSAtomicIncrement32(&cancelledCount)
39 | } else if task.faulted {
40 | OSAtomicIncrement32(&errorCount)
41 | }
42 |
43 | if OSAtomicDecrement32(&tasksCount) == 0 {
44 | if cancelledCount > 0 {
45 | tcs.cancel()
46 | } else if errorCount > 0 {
47 | #if swift(>=4.1)
48 | tcs.set(error: AggregateError(errors: tasks.compactMap({ $0.error })))
49 | #else
50 | tcs.set(error: AggregateError(errors: tasks.flatMap({ $0.error })))
51 | #endif
52 | } else {
53 | tcs.set(result: ())
54 | }
55 | }
56 | }
57 | }
58 | return tcs.task
59 | }
60 |
61 | /**
62 | Creates a task that will be completed after all of the input tasks have completed.
63 |
64 | - parameter tasks: Zero or more tasks to wait on for completion.
65 |
66 | - returns: A new task that will complete after all `tasks` are completed.
67 | */
68 | public class func whenAll(_ tasks: Task...) -> Task {
69 | return whenAll(tasks)
70 | }
71 |
72 | /**
73 | Creates a task that will be completed after all of the input tasks have completed.
74 |
75 | - parameter tasks: Array of tasks to wait on for completion.
76 |
77 | - returns: A new task that will complete after all `tasks` are completed.
78 | The result of the task is going an array of results of all tasks in the same order as they were provided.
79 | */
80 | public class func whenAllResult(_ tasks: [Task]) -> Task<[TResult]> {
81 | return whenAll(tasks).continueOnSuccessWithTask { task -> Task<[TResult]> in
82 | let results: [TResult] = tasks.map { task in
83 | guard let result = task.result else {
84 | // This should never happen.
85 | // If the task succeeded - there is no way result is `nil`, even in case TResult is optional,
86 | // because `task.result` would have a type of `Result??`, and we unwrap only one optional here.
87 | // If a task was cancelled, we should have never have gotten past 'continueOnSuccess'.
88 | // If a task errored, we should have returned a 'AggregateError' and never gotten past 'continueOnSuccess'.
89 | // If a task was pending, then something went horribly wrong.
90 | fatalError("Task is in unknown state \(task.state).")
91 | }
92 | return result
93 | }
94 | return Task<[TResult]>(results)
95 | }
96 | }
97 |
98 | /**
99 | Creates a task that will be completed after all of the input tasks have completed.
100 |
101 | - parameter tasks: Zero or more tasks to wait on for completion.
102 |
103 | - returns: A new task that will complete after all `tasks` are completed.
104 | The result of the task is going an array of results of all tasks in the same order as they were provided.
105 | */
106 | public class func whenAllResult(_ tasks: Task...) -> Task<[TResult]> {
107 | return whenAllResult(tasks)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/xcshareddata/xcschemes/BoltsSwift-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
52 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
77 |
78 |
84 |
85 |
86 |
87 |
93 |
94 |
100 |
101 |
102 |
103 |
105 |
106 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/Tests/ExecutorTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import XCTest
11 | import BoltsSwift
12 |
13 | class ExecutorTests: XCTestCase {
14 |
15 | func testDefaultExecute() {
16 | let expectation = self.expectation(description: name)
17 |
18 | var finished = false
19 | Executor.default.execute {
20 | expectation.fulfill()
21 | finished = true
22 | }
23 |
24 | XCTAssertTrue(finished)
25 | waitForTestExpectations()
26 | }
27 |
28 | func testImmediateExecute() {
29 | let expectation = self.expectation(description: name)
30 |
31 | var finished = false
32 | Executor.immediate.execute {
33 | expectation.fulfill()
34 | finished = true
35 | }
36 |
37 | XCTAssertTrue(finished)
38 | waitForTestExpectations()
39 | }
40 |
41 | func testMainThreadSyncExecute() {
42 | let expectation = self.expectation(description: name)
43 |
44 | var finished = false
45 | Executor.mainThread.execute {
46 | expectation.fulfill()
47 | finished = true
48 | }
49 |
50 | XCTAssertTrue(finished)
51 | waitForTestExpectations()
52 | }
53 |
54 | func testMainThreadAsyncExecute() {
55 | let expectation = self.expectation(description: name)
56 |
57 | var finished = false
58 | DispatchQueue.global(qos: .default).async {
59 | Executor.mainThread.execute {
60 | finished = true
61 | expectation.fulfill()
62 | }
63 | }
64 | waitForTestExpectations()
65 | XCTAssertTrue(finished)
66 | }
67 |
68 | func testQueueExecute() {
69 | let expectation = self.expectation(description: name)
70 | let semaphore = DispatchSemaphore(value: 0)
71 | var finished = false
72 |
73 | Executor.queue(.global(qos: .default)).execute {
74 | semaphore.wait()
75 | finished = true
76 | expectation.fulfill()
77 | }
78 |
79 | XCTAssertFalse(finished)
80 | semaphore.signal()
81 | waitForTestExpectations()
82 | XCTAssertTrue(finished)
83 | }
84 |
85 | func testClosureExecute() {
86 | let expectation = self.expectation(description: name)
87 |
88 | Executor.closure { closure in
89 | closure()
90 | }.execute { () -> Void in
91 | expectation.fulfill()
92 | }
93 |
94 | waitForTestExpectations()
95 | }
96 |
97 | func testEscapingClosureExecute() {
98 | let expectation = self.expectation(description: name)
99 | Executor.escapingClosure { closure in
100 | closure()
101 | }.execute { () -> Void in
102 | expectation.fulfill()
103 | }
104 |
105 | waitForTestExpectations()
106 | }
107 |
108 | func testOperationQueueExecute() {
109 | let expectation = self.expectation(description: name)
110 | let semaphore = DispatchSemaphore(value: 0)
111 | var finished = false
112 |
113 | let operationQueue = OperationQueue()
114 | Executor.operationQueue(operationQueue).execute {
115 | semaphore.wait()
116 | finished = true
117 | expectation.fulfill()
118 | }
119 |
120 | XCTAssertFalse(finished)
121 | semaphore.signal()
122 | waitForTestExpectations()
123 | XCTAssertTrue(finished)
124 | }
125 |
126 | // MARK: Descriptions
127 |
128 | func testDescriptions() {
129 | XCTAssertFalse(Executor.default.description.isEmpty)
130 | XCTAssertFalse(Executor.immediate.description.isEmpty)
131 | XCTAssertFalse(Executor.mainThread.description.isEmpty)
132 | XCTAssertFalse(Executor.queue(.global(qos: .default)).description.isEmpty)
133 | XCTAssertFalse(Executor.operationQueue(OperationQueue.current!).description.isEmpty)
134 | XCTAssertFalse(Executor.closure({ _ in }).description.isEmpty)
135 | }
136 |
137 | func testDebugDescriptions() {
138 | XCTAssertFalse(Executor.default.debugDescription.isEmpty)
139 | XCTAssertFalse(Executor.immediate.debugDescription.isEmpty)
140 | XCTAssertFalse(Executor.mainThread.debugDescription.isEmpty)
141 | XCTAssertFalse(Executor.queue(.global(qos: .default)).debugDescription.isEmpty)
142 | XCTAssertFalse(Executor.operationQueue(OperationQueue.current!).debugDescription.isEmpty)
143 | XCTAssertFalse(Executor.closure({ _ in }).debugDescription.isEmpty)
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Executor.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | /// `Executor` is an `enum`, that defines different strategies for calling closures.
13 | public enum Executor {
14 |
15 | /**
16 | Calls closures immediately unless the call stack gets too deep,
17 | in which case it dispatches the closure in the default priority queue.
18 | */
19 | case `default`
20 |
21 | /**
22 | Calls closures immediately.
23 | Tasks continuations will be run in the thread of the previous task.
24 | */
25 | case immediate
26 |
27 | /**
28 | Calls closures on the main thread.
29 | Will execute synchronously if already on the main thread, otherwise - will execute asynchronously.
30 | */
31 | case mainThread
32 |
33 | /**
34 | Dispatches closures on a GCD queue.
35 | */
36 | case queue(DispatchQueue)
37 |
38 | /**
39 | Adds closures to an operation queue.
40 | */
41 | case operationQueue(Foundation.OperationQueue)
42 |
43 | /**
44 | Passes closures to an executing closure.
45 | */
46 | case closure((() -> Void) -> Void)
47 |
48 | /**
49 | Passes escaping closures to an executing closure.
50 | */
51 | case escapingClosure((@escaping () -> Void) -> Void)
52 |
53 | /**
54 | Executes the given closure using the corresponding strategy.
55 |
56 | - parameter closure: The closure to execute.
57 | */
58 | public func execute(_ closure: @escaping () -> Void) {
59 | switch self {
60 | case .default:
61 | struct Static {
62 | static let taskDepthKey = "com.bolts.TaskDepthKey"
63 | static let maxTaskDepth = 20
64 | }
65 |
66 | let localThreadDictionary = Thread.current.threadDictionary
67 |
68 | var previousDepth: Int
69 | if let depth = localThreadDictionary[Static.taskDepthKey] as? Int {
70 | previousDepth = depth
71 | } else {
72 | previousDepth = 0
73 | }
74 |
75 | if previousDepth > Static.maxTaskDepth {
76 | DispatchQueue.global(qos: .default).async(execute: closure)
77 | } else {
78 | localThreadDictionary[Static.taskDepthKey] = previousDepth + 1
79 | closure()
80 | localThreadDictionary[Static.taskDepthKey] = previousDepth
81 | }
82 | case .immediate:
83 | closure()
84 | case .mainThread:
85 | if Thread.isMainThread {
86 | closure()
87 | } else {
88 | DispatchQueue.main.async(execute: closure)
89 | }
90 | case .queue(let queue):
91 | queue.async(execute: closure)
92 | case .operationQueue(let operationQueue):
93 | operationQueue.addOperation(closure)
94 | case .closure(let executingClosure):
95 | executingClosure(closure)
96 | case .escapingClosure(let executingEscapingClosure):
97 | executingEscapingClosure(closure)
98 | }
99 | }
100 | }
101 |
102 | extension Executor: CustomStringConvertible, CustomDebugStringConvertible {
103 | /// A textual representation of `self`.
104 | public var description: String {
105 | switch self {
106 | case .default:
107 | return "Default Executor"
108 | case .immediate:
109 | return "Immediate Executor"
110 | case .mainThread:
111 | return "MainThread Executor"
112 | case .queue:
113 | return "Executor with dispatch_queue"
114 | case .operationQueue:
115 | return "Executor with NSOperationQueue"
116 | case .closure:
117 | return "Executor with custom closure"
118 | case .escapingClosure:
119 | return "Executor with custom escaping closure"
120 | }
121 | }
122 |
123 | /// A textual representation of `self`, suitable for debugging.
124 | public var debugDescription: String {
125 | switch self {
126 | case .queue(let object):
127 | return "\(description): \(object)"
128 | case .operationQueue(let queue):
129 | return "\(description): \(queue)"
130 | case .closure(let closure):
131 | return "\(description): \(String(describing: closure))"
132 | case .escapingClosure(let closure):
133 | return "\(description): \(String(describing: closure))"
134 | default:
135 | return description
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [1.5.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.5.0) (2019-09-27)
4 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.4.0...1.5.0)
5 |
6 | **Implemented enhancements:**
7 |
8 | - Add support for Swift Package Manager. [\#92](https://github.com/BoltsFramework/Bolts-Swift/pull/92) ([nlutsenko](https://github.com/nlutsenko))
9 | - Update to Swift 5 and Xcode 11. [\#91](https://github.com/BoltsFramework/Bolts-Swift/pull/91) ([nlutsenko](https://github.com/nlutsenko))
10 |
11 | **Merged pull requests:**
12 |
13 | - \[TravisCI\] fix it, test with Swift 4.0 and 4.2 \(5.0 prepared\) [\#87](https://github.com/BoltsFramework/Bolts-Swift/pull/87) ([HeEAaD](https://github.com/HeEAaD))
14 | - Tweak README for readability & clarity [\#83](https://github.com/BoltsFramework/Bolts-Swift/pull/83) ([ermik](https://github.com/ermik))
15 | - Adding Code of Conduct file [\#79](https://github.com/BoltsFramework/Bolts-Swift/pull/79) ([facebook-github-bot](https://github.com/facebook-github-bot))
16 | - Add swift\_version to podspec [\#75](https://github.com/BoltsFramework/Bolts-Swift/pull/75) ([hcanzonetta](https://github.com/hcanzonetta))
17 |
18 | ## [1.4.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.4.0) (2018-07-19)
19 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.3.0...1.4.0)
20 |
21 | **Implemented enhancements:**
22 |
23 | - Remove flatMap because it is now deprecated in Swift 4.1 [\#71](https://github.com/BoltsFramework/Bolts-Swift/pull/71) ([sebleclerc](https://github.com/sebleclerc))
24 | - Swift 4.0 Support [\#64](https://github.com/BoltsFramework/Bolts-Swift/pull/64) ([nlutsenko](https://github.com/nlutsenko))
25 | - Adding a new executor which takes an escaping closure [\#58](https://github.com/BoltsFramework/Bolts-Swift/pull/58) ([sebleclerc](https://github.com/sebleclerc))
26 |
27 | **Merged pull requests:**
28 |
29 | - Changed casing of Executor enum value in README. [\#56](https://github.com/BoltsFramework/Bolts-Swift/pull/56) ([sjorsvb](https://github.com/sjorsvb))
30 | - Bolts 1.4.0 🔩 [\#74](https://github.com/BoltsFramework/Bolts-Swift/pull/74) ([nlutsenko](https://github.com/nlutsenko))
31 |
32 | ## [1.3.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.3.0) (2016-09-20)
33 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.2.0...1.3.0)
34 |
35 | **Implemented enhancements:**
36 |
37 | - Add Swift 3.0 support. [\#40](https://github.com/BoltsFramework/Bolts-Swift/pull/40) ([nlutsenko](https://github.com/nlutsenko))
38 |
39 | **Closed issues:**
40 |
41 | - Swift 3.0 Support [\#33](https://github.com/BoltsFramework/Bolts-Swift/issues/33)
42 |
43 | **Merged pull requests:**
44 |
45 | - Update a TaskCompletionSource usage example for Swift 3.0. [\#48](https://github.com/BoltsFramework/Bolts-Swift/pull/48) ([sapzildj](https://github.com/sapzildj))
46 | - Bolts 1.3.0 🔩 [\#42](https://github.com/BoltsFramework/Bolts-Swift/pull/42) ([nlutsenko](https://github.com/nlutsenko))
47 | - Set lowest deployment macOS target to 10.10. [\#41](https://github.com/BoltsFramework/Bolts-Swift/pull/41) ([nlutsenko](https://github.com/nlutsenko))
48 | - Fix README for TaskCompletionSource.cancel\(\) [\#37](https://github.com/BoltsFramework/Bolts-Swift/pull/37) ([ceyhun](https://github.com/ceyhun))
49 |
50 | ## [1.2.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.2.0) (2016-07-25)
51 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.1.0...1.2.0)
52 |
53 | **Implemented enhancements:**
54 |
55 | - Implement new set of continuations for error-only use case. [\#17](https://github.com/BoltsFramework/Bolts-Swift/issues/17)
56 | - Make all 'trySet', 'set' functions to use explicit argument labels. [\#30](https://github.com/BoltsFramework/Bolts-Swift/pull/30) ([nlutsenko](https://github.com/nlutsenko))
57 | - Update project/tests for Xcode 8 and Swift 2.3. [\#27](https://github.com/BoltsFramework/Bolts-Swift/pull/27) ([nlutsenko](https://github.com/nlutsenko))
58 | - Make CompletedCondtion optional, should improve memory usage slightly. [\#25](https://github.com/BoltsFramework/Bolts-Swift/pull/25) ([richardjrossiii](https://github.com/richardjrossiii))
59 | - Add continueOnErrorWith, continueOnErrorWithTask. [\#18](https://github.com/BoltsFramework/Bolts-Swift/pull/18) ([nlutsenko](https://github.com/nlutsenko))
60 |
61 | **Fixed bugs:**
62 |
63 | - Resolve retain cycle in Task [\#19](https://github.com/BoltsFramework/Bolts-Swift/pull/19) ([mmtootmm](https://github.com/mmtootmm))
64 |
65 | **Merged pull requests:**
66 |
67 | - Refactor continuation to be better, faster, stronger. [\#20](https://github.com/BoltsFramework/Bolts-Swift/pull/20) ([richardjrossiii](https://github.com/richardjrossiii))
68 | - Bolts 1.2.0 🔩 [\#34](https://github.com/BoltsFramework/Bolts-Swift/pull/34) ([nlutsenko](https://github.com/nlutsenko))
69 | - Migrate all targets to shared configurations from xctoolchain. [\#32](https://github.com/BoltsFramework/Bolts-Swift/pull/32) ([nlutsenko](https://github.com/nlutsenko))
70 | - Add swiftlint to Travis-CI. [\#29](https://github.com/BoltsFramework/Bolts-Swift/pull/29) ([nlutsenko](https://github.com/nlutsenko))
71 | - Split Task into multiple files. [\#24](https://github.com/BoltsFramework/Bolts-Swift/pull/24) ([richardjrossiii](https://github.com/richardjrossiii))
72 | - Update installation instructions in README. [\#22](https://github.com/BoltsFramework/Bolts-Swift/pull/22) ([nlutsenko](https://github.com/nlutsenko))
73 |
74 | ## [1.1.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.1.0) (2016-05-04)
75 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.0.1...1.1.0)
76 |
77 | **Implemented enhancements:**
78 |
79 | - Add ability to throw errors in all Task continuations that return a Task. [\#14](https://github.com/BoltsFramework/Bolts-Swift/pull/14) ([nlutsenko](https://github.com/nlutsenko))
80 | - Improve and add missing documentation. [\#10](https://github.com/BoltsFramework/Bolts-Swift/pull/10) ([nlutsenko](https://github.com/nlutsenko))
81 |
82 | **Fixed bugs:**
83 |
84 | - Fix usage of CancelledError, add tests for error handling inside tasks. [\#13](https://github.com/BoltsFramework/Bolts-Swift/pull/13) ([nlutsenko](https://github.com/nlutsenko))
85 |
86 | **Merged pull requests:**
87 |
88 | - Bolts 1.1.0 🔩 [\#16](https://github.com/BoltsFramework/Bolts-Swift/pull/16) ([nlutsenko](https://github.com/nlutsenko))
89 | - Add more tests and fix documentation. [\#12](https://github.com/BoltsFramework/Bolts-Swift/pull/12) ([nlutsenko](https://github.com/nlutsenko))
90 | - Use Xcode 7.3 for Travis-CI. [\#11](https://github.com/BoltsFramework/Bolts-Swift/pull/11) ([nlutsenko](https://github.com/nlutsenko))
91 |
92 | ## [1.0.1](https://github.com/BoltsFramework/Bolts-Swift/tree/1.0.1) (2016-03-24)
93 | [Full Changelog](https://github.com/BoltsFramework/Bolts-Swift/compare/1.0.0...1.0.1)
94 |
95 | **Implemented enhancements:**
96 |
97 | - Make tests less flaky and be able to run under Swift 2.2/Xcode 7.3. [\#1](https://github.com/BoltsFramework/Bolts-Swift/pull/1) ([nlutsenko](https://github.com/nlutsenko))
98 |
99 | **Fixed bugs:**
100 |
101 | - Task never completes [\#5](https://github.com/BoltsFramework/Bolts-Swift/issues/5)
102 | - Fix optimized away TaskCompletionSource non-try methods. [\#7](https://github.com/BoltsFramework/Bolts-Swift/pull/7) ([nlutsenko](https://github.com/nlutsenko))
103 |
104 | **Merged pull requests:**
105 |
106 | - Bolts 1.0.1 🔩 [\#9](https://github.com/BoltsFramework/Bolts-Swift/pull/9) ([nlutsenko](https://github.com/nlutsenko))
107 | - Add tests for release configuration in addition to Debug one. [\#8](https://github.com/BoltsFramework/Bolts-Swift/pull/8) ([nlutsenko](https://github.com/nlutsenko))
108 | - Use common expectation wait method in tests. [\#6](https://github.com/BoltsFramework/Bolts-Swift/pull/6) ([nlutsenko](https://github.com/nlutsenko))
109 | - README: Fix syntax in example code. [\#4](https://github.com/BoltsFramework/Bolts-Swift/pull/4) ([Lukas-Stuehrk](https://github.com/Lukas-Stuehrk))
110 | - Fix typo in README. [\#3](https://github.com/BoltsFramework/Bolts-Swift/pull/3) ([Lukas-Stuehrk](https://github.com/Lukas-Stuehrk))
111 | - Fix typos in README [\#2](https://github.com/BoltsFramework/Bolts-Swift/pull/2) ([richardjrossiii](https://github.com/richardjrossiii))
112 |
113 | ## [1.0.0](https://github.com/BoltsFramework/Bolts-Swift/tree/1.0.0) (2016-03-17)
114 |
115 |
116 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bolts in Swift
2 |
3 | ![Platforms][platforms-svg]
4 | ![Swift Version][swift-version-svg]
5 | [![License][license-svg]][license-link]
6 |
7 | [![Podspec][podspec-svg]][podspec-link]
8 | [![Carthage compatible][carthage-svg]](carthage-link)
9 | [![Swift Package Manager compatible][swiftpm-svg]](swiftpm-link)
10 |
11 | [![Build Status][build-status-svg]][build-status-link]
12 | [![Coverage Status][coverage-status-svg]][coverage-status-link]
13 |
14 | Bolts is a collection of low-level libraries designed to make developing mobile apps easier. Bolts was designed by Parse and Facebook for our own internal use, and we have decided to open source these libraries to make them available to others.
15 |
16 | ## Tasks
17 |
18 | Bolts Tasks is a complete implementation of futures/promises for iOS/OS X/watchOS/tvOS and any platform that supports Swift.
19 | A task represents the result of an asynchronous operation, which typically would be returned from a function.
20 | In addition to being able to have different states `completed`/`faulted`/`cancelled` they provide these benefits:
21 |
22 | - `Tasks` consume fewer system resources, since they don't occupy a thread while waiting on other `Tasks`.
23 | - `Tasks` could be performed/chained in a row which will not create nested "pyramid" code as you would get when using only callbacks.
24 | - `Tasks` are fully composable, allowing you to perform branching, parallelism, and complex error handling, without the spaghetti code of having many named callbacks.
25 | - `Tasks` allow you to arrange code in the order that it executes, rather than having to split your logic across scattered callback functions.
26 | - `Tasks` don't depend on any particular threading model. So you can use concepts like operation queues/dispatch queues or even thread executors.
27 | - `Tasks` could be used synchronously or asynchronously, providing the same benefit of different results of any function/operation.
28 |
29 | ## Getting Started
30 |
31 | - **[CocoaPods](https://cocoapods.org)**
32 |
33 | Add the following line to your Podfile:
34 |
35 | ```ruby
36 | pod 'Bolts-Swift'
37 | ```
38 |
39 | Run `pod install`, and you should now have the latest parse release.
40 |
41 | - **[Carthage](https://github.com/carthage/carthage)**
42 |
43 | Add the following line to your Cartfile:
44 |
45 | ```
46 | github "BoltsFramework/Bolts-Swift"
47 | ```
48 |
49 | Run `carthage update`, and you should now have the latest version of Bolts in your Carthage folder.
50 |
51 | - **Using Bolts as a sub-project**
52 |
53 | You can also include Bolts as a subproject inside of your application if you'd prefer, although we do not recommend this, as it will increase your indexing time significantly. To do so, just drag and drop the `BoltsSwift.xcodeproj` file into your workspace.
54 |
55 | - **Import Bolts**
56 |
57 | Now that you have the framework linked to your application - add the folowing line in every `.swift` that you want to use Bolts from:
58 |
59 | ```
60 | import BoltsSwift
61 | ```
62 |
63 | ## Chaining Tasks
64 |
65 | There are special methods you can call on a task which accept a closure argument and will return the task object. Because they return tasks it means you can keep calling these methods – also known as _chaining_ – to perform logic in stages. This is a powerful approach that makes your code read as a sequence of steps, while harnessing the power of asynchronous execution. Here are 3 key functions you should know:
66 |
67 | 1. Use `continueWith` to inspect the task after it has ran and perform more operations with the result
68 | 1. Use `continueWithTask` to add more work based on the result of the previous task
69 | 1. Use `continueOnSuccessWith` to perform logic only when task executed without errors
70 |
71 | For full list of available methods please see source code at **[Task+ContinueWith.swift][continueWith-source]**
72 |
73 | ### continueWith
74 |
75 | Every `Task` has a function named `continueWith`, which takes a continuation closure. A continuation will be executed when the task is complete. You can the inspect the task to check if it was successful and to get its result.
76 |
77 | ```swift
78 | save(object).continueWith { task in
79 | if task.cancelled {
80 | // Save was cancelled
81 | } else if task.faulted {
82 | // Save failed
83 | } else {
84 | // Object was successfully saved
85 | let result = task.result
86 | }
87 | }
88 | ```
89 |
90 | ### continueOnSuccessWith
91 |
92 | In many cases, you only want to do more work if the previous task was successful, and propagate any error or cancellation to be dealt with later. To do this, use `continueOnSuccessWith` function:
93 |
94 | ```swift
95 | save(object).continueOnSuccessWith { result in
96 | // Closure receives the result of a succesfully performed task
97 | // If result is invalid throw an error which will mark task as faulted
98 | }
99 | ```
100 |
101 | Underneath, `continueOnSuccessWith` is calling `continueOnSuccessWithTask` method which is more powerful and useful for situations where you want to spawn additional work.
102 |
103 | ### continueOnSuccessWithTask
104 |
105 | As you saw above, if you return an object from `continueWith` function – it will become a result the Task. But what if there is more work to do? If you want to call into more tasks and return their results instead – you can use `continueWithTask`. This gives you an ability to chain more asynchronous work together.
106 |
107 | In the following example we want to fetch a user profile, then fetch a profile image, and if any of these operations failed - we still want to display an placeholder image:
108 |
109 | ```swift
110 | fetchProfile(user).continueOnSuccessWithTask { task in
111 | return fetchProfileImage(task.result);
112 | }.continueWith { task in
113 | if let image = task.result {
114 | return image
115 | }
116 | return ProfileImagePlaceholder()
117 | }
118 | ```
119 |
120 | ## Creating Tasks
121 |
122 | To create a task - you would need a `TaskCompletionSource`, which is a consumer end of any `Task`, which gives you an ability to control whether the task is completed/faulted or cancelled.
123 | After you create a `TaskCompletionSource`, you need to call `setResult()`/`setError()`/`cancel()` to trigger its continuations and change its state.
124 |
125 | ```swift
126 | func fetch(object: PFObject) -> Task {
127 | let taskCompletionSource = TaskCompletionSource()
128 | object.fetchInBackgroundWithBlock() { (object: PFObject?, error: NSError?) in
129 | if let error = error {
130 | taskCompletionSource.setError(error)
131 | } else if let object = object {
132 | taskCompletionSource.setResult(object)
133 | } else {
134 | taskCompletionSource.cancel()
135 | }
136 | }
137 | return taskCompletionSource.task
138 | }
139 | ```
140 |
141 | ## Tasks in Parallel
142 |
143 | You can also perform several tasks in parallel and chain the result of all of them using `whenAll()` function.
144 |
145 | ```swift
146 | let query = PFQuery(className: "Comments")
147 | find(query).continueWithTask { task in
148 | var tasks: [Task] = []
149 | task.result?.forEach { comment in
150 | tasks.append(self.deleteComment(comment))
151 | }
152 | return Task.whenAll(tasks)
153 | }.continueOnSuccessWith { task in
154 | // All comments were deleted
155 | }
156 | ```
157 |
158 | ## Task Executors
159 |
160 | Both `continueWith()` and `continueWithTask()` functions accept an optional executor parameter. It allows you to control how the continuation closure is executed.
161 | The default executor will dispatch to global dispatch queue, but you can provide your own executor to schedule work in a specific way.
162 | For example, if you want to continue with work on the main thread:
163 |
164 | ```swift
165 | fetch(object).continueWith(Executor.mainThread) { task in
166 | // This closure will be executor on the main application's thread
167 | }
168 | ```
169 |
170 | ## How Do I Contribute?
171 |
172 | We want to make contributing to this project as easy and transparent as possible. Please refer to the [Contribution Guidelines][contributing].
173 |
174 | [releases]: https://github.com/BoltsFramework/Bolts-Swift/releases
175 | [contributing]: https://github.com/BoltsFramework/Bolts-Swift/blob/master/CONTRIBUTING.md
176 |
177 | [build-status-svg]: https://img.shields.io/travis/BoltsFramework/Bolts-Swift/master.svg
178 | [build-status-link]: https://travis-ci.org/BoltsFramework/Bolts-Swift/branches
179 |
180 | [coverage-status-svg]: https://img.shields.io/codecov/c/github/BoltsFramework/Bolts-Swift/master.svg
181 | [coverage-status-link]: https://codecov.io/github/BoltsFramework/Bolts-Swift?branch=master
182 |
183 | [license-svg]: https://img.shields.io/badge/license-BSD-lightgrey.svg
184 | [license-link]: https://github.com/BoltsFramework/Bolts-Swift/blob/master/LICENSE
185 |
186 | [podspec-svg]: https://img.shields.io/cocoapods/v/Bolts-Swift.svg
187 | [podspec-link]: https://cocoapods.org/pods/Bolts-Swift
188 |
189 | [carthage-svg]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat
190 | [carthage-link]: https://github.com/carthage/carthage
191 |
192 | [swiftpm-svg]: https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg?style=flat
193 | [swiftpm-link]: https://github.com/apple/swift-package-manager
194 |
195 | [platforms-svg]: http://img.shields.io/cocoapods/p/Bolts-Swift.svg?style=flat
196 | [swift-version-svg]: https://img.shields.io/badge/Swift-5-orange.svg
197 |
198 | [continueWith-source]: https://github.com/BoltsFramework/Bolts-Swift/blob/master/Sources/BoltsSwift/Task%2BContinueWith.swift
199 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Task+ContinueWith.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | //--------------------------------------
13 | // MARK: - ContinueWith
14 | //--------------------------------------
15 |
16 | extension Task {
17 | /**
18 | Internal continueWithTask. This is the method that all other continuations must go through.
19 |
20 | - parameter executor: The executor to invoke the closure on.
21 | - parameter options: The options to run the closure with
22 | - parameter continuation: The closure to execute.
23 |
24 | - returns: The task resulting from the continuation
25 | */
26 | fileprivate func continueWithTask(_ executor: Executor,
27 | options: TaskContinuationOptions,
28 | continuation: @escaping ((Task) throws -> Task)
29 | ) -> Task {
30 | let taskCompletionSource = TaskCompletionSource()
31 | let wrapperContinuation = {
32 | switch self.state {
33 | case .success where options.contains(.RunOnSuccess): fallthrough
34 | case .error where options.contains(.RunOnError): fallthrough
35 | case .cancelled where options.contains(.RunOnCancelled):
36 | executor.execute {
37 | let wrappedState = TaskState>.fromClosure {
38 | try continuation(self)
39 | }
40 | switch wrappedState {
41 | case .success(let nextTask):
42 | switch nextTask.state {
43 | case .pending:
44 | nextTask.continueWith { nextTask in
45 | taskCompletionSource.setState(nextTask.state)
46 | }
47 | default:
48 | taskCompletionSource.setState(nextTask.state)
49 | }
50 | case .error(let error):
51 | taskCompletionSource.set(error: error)
52 | case .cancelled:
53 | taskCompletionSource.cancel()
54 | default: abort() // This should never happen.
55 | }
56 | }
57 |
58 | case .success(let result as S):
59 | // This is for continueOnErrorWith - the type of the result doesn't change, so we can pass it through
60 | taskCompletionSource.set(result: result)
61 |
62 | case .error(let error):
63 | taskCompletionSource.set(error: error)
64 |
65 | case .cancelled:
66 | taskCompletionSource.cancel()
67 |
68 | default:
69 | fatalError("Task was in an invalid state \(self.state)")
70 | }
71 | }
72 | appendOrRunContinuation(wrapperContinuation)
73 | return taskCompletionSource.task
74 | }
75 |
76 | /**
77 | Enqueues a given closure to be run once this task is complete.
78 |
79 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
80 | - parameter continuation: The closure that returns the result of the task.
81 |
82 | - returns: A task that will be completed with a result from a given closure.
83 | */
84 | @discardableResult
85 | public func continueWith(_ executor: Executor = .default, continuation: @escaping ((Task) throws -> S)) -> Task {
86 | return continueWithTask(executor) { task in
87 | let state = TaskState.fromClosure({
88 | try continuation(task)
89 | })
90 | return Task(state: state)
91 | }
92 | }
93 |
94 | /**
95 | Enqueues a given closure to be run once this task is complete.
96 |
97 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
98 | - parameter continuation: The closure that returns a task to chain on.
99 |
100 | - returns: A task that will be completed when a task returned from a closure is completed.
101 | */
102 | @discardableResult
103 | public func continueWithTask(_ executor: Executor = .default, continuation: @escaping ((Task) throws -> Task)) -> Task {
104 | return continueWithTask(executor, options: .RunAlways, continuation: continuation)
105 | }
106 | }
107 |
108 | //--------------------------------------
109 | // MARK: - ContinueOnSuccessWith
110 | //--------------------------------------
111 |
112 | extension Task {
113 | /**
114 | Enqueues a given closure to be run once this task completes with success (has intended result).
115 |
116 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
117 | - parameter continuation: The closure that returns a task to chain on.
118 |
119 | - returns: A task that will be completed when a task returned from a closure is completed.
120 | */
121 | @discardableResult
122 | public func continueOnSuccessWith(_ executor: Executor = .default,
123 | continuation: @escaping ((TResult) throws -> S)) -> Task {
124 | return continueOnSuccessWithTask(executor) { taskResult in
125 | let state = TaskState.fromClosure({
126 | try continuation(taskResult)
127 | })
128 | return Task(state: state)
129 | }
130 | }
131 |
132 | /**
133 | Enqueues a given closure to be run once this task completes with success (has intended result).
134 |
135 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
136 | - parameter continuation: The closure that returns a task to chain on.
137 |
138 | - returns: A task that will be completed when a task returned from a closure is completed.
139 | */
140 | @discardableResult
141 | public func continueOnSuccessWithTask(_ executor: Executor = .default,
142 | continuation: @escaping ((TResult) throws -> Task)) -> Task {
143 | return continueWithTask(executor, options: .RunOnSuccess) { task in
144 | return try continuation(task.result!)
145 | }
146 | }
147 | }
148 |
149 | //--------------------------------------
150 | // MARK: - ContinueOnErrorWith
151 | //--------------------------------------
152 |
153 | extension Task {
154 | /**
155 | Enqueues a given closure to be run once this task completes with error.
156 |
157 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
158 | - parameter continuation: The closure that returns a task to chain on.
159 |
160 | - returns: A task that will be completed when a task returned from a closure is completed.
161 | */
162 | @discardableResult
163 | public func continueOnErrorWith(_ executor: Executor = .default, continuation: @escaping ((E) throws -> TResult)) -> Task {
164 | return continueOnErrorWithTask(executor) { (error: E) in
165 | let state = TaskState.fromClosure({
166 | try continuation(error)
167 | })
168 | return Task(state: state)
169 | }
170 | }
171 |
172 | /**
173 | Enqueues a given closure to be run once this task completes with error.
174 |
175 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
176 | - parameter continuation: The closure that returns a task to chain on.
177 |
178 | - returns: A task that will be completed when a task returned from a closure is completed.
179 | */
180 | @discardableResult
181 | public func continueOnErrorWith(_ executor: Executor = .default, continuation: @escaping ((Error) throws -> TResult)) -> Task {
182 | return continueOnErrorWithTask(executor) { (error: Error) in
183 | let state = TaskState.fromClosure({
184 | try continuation(error)
185 | })
186 | return Task(state: state)
187 | }
188 | }
189 |
190 | /**
191 | Enqueues a given closure to be run once this task completes with error.
192 |
193 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
194 | - parameter continuation: The closure that returns a task to chain on.
195 |
196 | - returns: A task that will be completed when a task returned from a closure is completed.
197 | */
198 | @discardableResult
199 | public func continueOnErrorWithTask(_ executor: Executor = .default, continuation: @escaping ((E) throws -> Task)) -> Task {
200 | return continueOnErrorWithTask(executor) { (error: Error) in
201 | if let error = error as? E {
202 | return try continuation(error)
203 | }
204 | return Task(state: .error(error))
205 | }
206 | }
207 |
208 | /**
209 | Enqueues a given closure to be run once this task completes with error.
210 |
211 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
212 | - parameter continuation: The closure that returns a task to chain on.
213 |
214 | - returns: A task that will be completed when a task returned from a closure is completed.
215 | */
216 | @discardableResult
217 | public func continueOnErrorWithTask(_ executor: Executor = .default, continuation: @escaping ((Error) throws -> Task)) -> Task {
218 | return continueWithTask(executor, options: .RunOnError) { task in
219 | return try continuation(task.error!)
220 | }
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/Sources/BoltsSwift/Task.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import Foundation
11 |
12 | enum TaskState {
13 | case pending
14 | case success(TResult)
15 | case error(Error)
16 | case cancelled
17 |
18 | static func fromClosure(_ closure: () throws -> TResult) -> TaskState {
19 | do {
20 | return .success(try closure())
21 | } catch is CancelledError {
22 | return .cancelled
23 | } catch {
24 | return .error(error)
25 | }
26 | }
27 | }
28 |
29 | struct TaskContinuationOptions: OptionSet {
30 | let rawValue: Int
31 | init(rawValue: Int) {
32 | self.rawValue = rawValue
33 | }
34 |
35 | static let RunOnSuccess = TaskContinuationOptions(rawValue: 1 << 0)
36 | static let RunOnError = TaskContinuationOptions(rawValue: 1 << 1)
37 | static let RunOnCancelled = TaskContinuationOptions(rawValue: 1 << 2)
38 |
39 | static let RunAlways: TaskContinuationOptions = [ .RunOnSuccess, .RunOnError, .RunOnCancelled ]
40 | }
41 |
42 | //--------------------------------------
43 | // MARK: - Task
44 | //--------------------------------------
45 |
46 | ///
47 | /// The consumer view of a Task.
48 | /// Task has methods to inspect the state of the task, and to add continuations to be run once the task is complete.
49 | ///
50 | public final class Task {
51 | public typealias Continuation = () -> Void
52 |
53 | fileprivate let synchronizationQueue = DispatchQueue(label: "com.bolts.task", attributes: DispatchQueue.Attributes.concurrent)
54 | fileprivate var _completedCondition: NSCondition?
55 |
56 | fileprivate var _state: TaskState = .pending
57 | fileprivate var _continuations: [Continuation] = Array()
58 |
59 | // MARK: Initializers
60 |
61 | init() {}
62 |
63 | init(state: TaskState) {
64 | _state = state
65 | }
66 |
67 | /**
68 | Creates a task that is already completed with the given result.
69 |
70 | - parameter result: The task result.
71 | */
72 | public init(_ result: TResult) {
73 | _state = .success(result)
74 | }
75 |
76 | /**
77 | Initializes a task that is already completed with the given error.
78 |
79 | - parameter error: The task error.
80 | */
81 | public init(error: Error) {
82 | _state = .error(error)
83 | }
84 |
85 | /**
86 | Creates a cancelled task.
87 |
88 | - returns: A cancelled task.
89 | */
90 | public class func cancelledTask() -> Self {
91 | // Swift prevents this method from being called `cancelled` due to the `cancelled` instance var. This is most likely a bug.
92 | return self.init(state: .cancelled)
93 | }
94 |
95 | class func emptyTask() -> Task {
96 | return Task(state: .success(()))
97 | }
98 |
99 | // MARK: Execute
100 |
101 | /**
102 | Creates a task that will complete with the result of the given closure.
103 |
104 | - note: The closure cannot make the returned task to fail. Use the other `execute` overload for this.
105 |
106 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
107 | - parameter closure: The closure that returns the result of the task.
108 | The returned task will complete when the closure completes.
109 | */
110 | public convenience init(_ executor: Executor = .default, closure: @escaping (() throws -> TResult)) {
111 | self.init(state: .pending)
112 | executor.execute {
113 | self.trySet(state: TaskState.fromClosure(closure))
114 | }
115 | }
116 |
117 | /**
118 | Creates a task that will continue with the task returned by the given closure.
119 |
120 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
121 | - parameter closure: The closure that returns the continuation task.
122 | The returned task will complete when the continuation task completes.
123 |
124 | - returns: A task that will continue with the task returned by the given closure.
125 | */
126 | public class func execute(_ executor: Executor = .default, closure: @escaping (() throws -> TResult)) -> Task {
127 | return Task(executor, closure: closure)
128 | }
129 |
130 | /**
131 | Creates a task that will continue with the task returned by the given closure.
132 |
133 | - parameter executor: Determines how the the closure is called. The default is to call the closure immediately.
134 | - parameter closure: The closure that returns the continuation task.
135 | The returned task will complete when the continuation task completes.
136 |
137 | - returns: A task that will continue with the task returned by the given closure.
138 | */
139 | public class func executeWithTask(_ executor: Executor = .default, closure: @escaping (() throws -> Task)) -> Task {
140 | return emptyTask().continueWithTask(executor) { _ in
141 | return try closure()
142 | }
143 | }
144 |
145 | // MARK: State Accessors
146 |
147 | /// Whether this task is completed. A completed task can also be faulted or cancelled.
148 | public var completed: Bool {
149 | switch state {
150 | case .pending:
151 | return false
152 | default:
153 | return true
154 | }
155 | }
156 |
157 | /// Whether this task has completed due to an error or exception. A `faulted` task is also completed.
158 | public var faulted: Bool {
159 | switch state {
160 | case .error:
161 | return true
162 | default:
163 | return false
164 | }
165 | }
166 |
167 | /// Whether this task has been cancelled. A `cancelled` task is also completed.
168 | public var cancelled: Bool {
169 | switch state {
170 | case .cancelled:
171 | return true
172 | default:
173 | return false
174 | }
175 | }
176 |
177 | /// The result of a successful task. Won't be set until the task completes with a `result`.
178 | public var result: TResult? {
179 | switch state {
180 | case .success(let result):
181 | return result
182 | default:
183 | break
184 | }
185 | return nil
186 | }
187 |
188 | /// The error of a errored task. Won't be set until the task completes with `error`.
189 | public var error: Error? {
190 | switch state {
191 | case .error(let error):
192 | return error
193 | default:
194 | break
195 | }
196 | return nil
197 | }
198 |
199 | /**
200 | Waits until this operation is completed.
201 |
202 | This method is inefficient and consumes a thread resource while it's running.
203 | It should be avoided. This method logs a warning message if it is used on the main thread.
204 | */
205 | public func waitUntilCompleted() {
206 | if Thread.isMainThread {
207 | debugPrint("Warning: A long-running operation is being executed on the main thread waiting on \(self).")
208 | }
209 |
210 | var conditon: NSCondition?
211 | synchronizationQueue.sync(flags: .barrier, execute: {
212 | if case .pending = self._state {
213 | conditon = self._completedCondition ?? NSCondition()
214 | self._completedCondition = conditon
215 | }
216 | })
217 |
218 | guard let condition = conditon else {
219 | // Task should have been completed
220 | precondition(completed)
221 | return
222 | }
223 |
224 | condition.lock()
225 | while !completed {
226 | condition.wait()
227 | }
228 | condition.unlock()
229 |
230 | synchronizationQueue.sync(flags: .barrier, execute: {
231 | self._completedCondition = nil
232 | })
233 | }
234 |
235 | // MARK: State Change
236 |
237 | @discardableResult
238 | func trySet(state: TaskState) -> Bool {
239 | var stateChanged = false
240 |
241 | var continuations: [Continuation]?
242 | var completedCondition: NSCondition?
243 | synchronizationQueue.sync(flags: .barrier, execute: {
244 | switch self._state {
245 | case .pending:
246 | stateChanged = true
247 | self._state = state
248 | continuations = self._continuations
249 | completedCondition = self._completedCondition
250 | self._continuations.removeAll()
251 | default:
252 | break
253 | }
254 | })
255 | if stateChanged {
256 | completedCondition?.lock()
257 | completedCondition?.broadcast()
258 | completedCondition?.unlock()
259 |
260 | for continuation in continuations! {
261 | continuation()
262 | }
263 | }
264 |
265 | return stateChanged
266 | }
267 |
268 | // MARK: Internal
269 |
270 | func appendOrRunContinuation(_ continuation: @escaping Continuation) {
271 | var runContinuation = false
272 | synchronizationQueue.sync(flags: .barrier, execute: {
273 | switch self._state {
274 | case .pending:
275 | self._continuations.append(continuation)
276 | default:
277 | runContinuation = true
278 | }
279 | })
280 | if runContinuation {
281 | continuation()
282 | }
283 | }
284 |
285 | var state: TaskState {
286 | var value: TaskState?
287 | synchronizationQueue.sync {
288 | value = self._state
289 | }
290 | return value!
291 | }
292 | }
293 |
294 | //--------------------------------------
295 | // MARK: - Description
296 | //--------------------------------------
297 |
298 | extension Task: CustomStringConvertible, CustomDebugStringConvertible {
299 | /// A textual representation of `self`.
300 | public var description: String {
301 | return "Task: \(self.state)"
302 | }
303 |
304 | /// A textual representation of `self`, suitable for debugging.
305 | public var debugDescription: String {
306 | return "Task: \(self.state)"
307 | }
308 | }
309 |
--------------------------------------------------------------------------------
/Tests/TaskTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | import XCTest
11 | import BoltsSwift
12 |
13 | class TaskTests: XCTestCase {
14 |
15 | // MARK: Initializers
16 |
17 | func testWithResult() {
18 | let task = Task(name)
19 |
20 | XCTAssertNotNil(task.result)
21 | XCTAssertEqual(task.result, name)
22 | XCTAssertTrue(task.completed)
23 | XCTAssertFalse(task.faulted)
24 | XCTAssertFalse(task.cancelled)
25 | XCTAssertNil(task.error)
26 | }
27 |
28 | func testWithError() {
29 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
30 | let task = Task(error: error)
31 |
32 | XCTAssertNil(task.result)
33 | XCTAssertTrue(task.completed)
34 | XCTAssertTrue(task.faulted)
35 | XCTAssertFalse(task.cancelled)
36 | XCTAssertNotNil(task.error)
37 | XCTAssertEqual(task.error as NSError?, error)
38 | }
39 |
40 | func testCancelledTask() {
41 | let task = Task.cancelledTask()
42 |
43 | XCTAssertNil(task.result)
44 | XCTAssertTrue(task.completed)
45 | XCTAssertFalse(task.faulted)
46 | XCTAssertTrue(task.cancelled)
47 | XCTAssertNil(task.error)
48 | }
49 |
50 | // MARK: Task with Delay
51 |
52 | func testWithDelay() {
53 | let expectation = self.expectation(description: name)
54 | let task = Task.withDelay(0.01)
55 | task.continueWith { _ in
56 | expectation.fulfill()
57 | }
58 |
59 | XCTAssertFalse(task.completed)
60 | waitForTestExpectations()
61 | }
62 |
63 | // MARK: Execute
64 |
65 | func testExecuteWithClosureReturningNil() {
66 | let expectation = self.expectation(description: name)
67 | let task = Task {
68 | expectation.fulfill()
69 | return "Hello, World!"
70 | }
71 | waitForTestExpectations()
72 | XCTAssertEqual(task.result, "Hello, World!")
73 | }
74 |
75 | func testConstructorWithClosureReturningValue() {
76 | let expectation = self.expectation(description: name)
77 | let task = Task {
78 | expectation.fulfill()
79 | return self.name
80 | }
81 | waitForTestExpectations()
82 | XCTAssertNotNil(task.result)
83 | XCTAssertEqual(task.result, name)
84 | }
85 |
86 | func testExecuteWithClosureReturningValue() {
87 | let expectation = self.expectation(description: name)
88 | let task = Task.execute {
89 | expectation.fulfill()
90 | return self.name
91 | }
92 | waitForTestExpectations()
93 | XCTAssertNotNil(task.result)
94 | XCTAssertEqual(task.result, name)
95 | }
96 |
97 | func testExecuteWithClosureReturningTaskWithResult() {
98 | let expectation = self.expectation(description: name)
99 | let task = Task.executeWithTask { () -> Task in
100 | expectation.fulfill()
101 | return Task(10)
102 | }
103 | waitForTestExpectations()
104 | XCTAssertNotNil(task.result)
105 | XCTAssertEqual(task.result, 10)
106 | }
107 |
108 | func testExecuteWithClosureReturningCancelledTask() {
109 | let expectation = self.expectation(description: name)
110 | let task = Task.executeWithTask { () -> Task in
111 | expectation.fulfill()
112 | return Task.cancelledTask()
113 | }
114 | waitForTestExpectations()
115 | XCTAssertTrue(task.cancelled)
116 | }
117 |
118 | func textExecuteWithClosureThrowingError() {
119 | let expectation = self.expectation(description: name)
120 | let task = Task.execute {
121 | defer {
122 | expectation.fulfill()
123 | }
124 | throw NSError(domain: "com.bolts", code: 1, userInfo: nil)
125 | }
126 | waitForTestExpectations()
127 | XCTAssertNotNil(task.error)
128 | }
129 |
130 | func testExecuteWithClosureThrowingCancelledError() {
131 | let expectation = self.expectation(description: name)
132 | let task = Task.execute {
133 | defer {
134 | expectation.fulfill()
135 | }
136 | throw CancelledError()
137 | }
138 | waitForTestExpectations()
139 | XCTAssertTrue(task.cancelled)
140 | XCTAssertNil(task.error)
141 | }
142 |
143 | func textExecuteWithTaskClosureThrowingError() {
144 | let expectation = self.expectation(description: name)
145 | let task = Task.executeWithTask {
146 | defer {
147 | expectation.fulfill()
148 | }
149 | throw NSError(domain: "com.bolts", code: 1, userInfo: nil)
150 | }
151 | waitForTestExpectations()
152 | XCTAssertNotNil(task.error)
153 | }
154 |
155 | func testExecuteWithTaskClosureThrowingCancelledError() {
156 | let expectation = self.expectation(description: name)
157 | let task = Task.executeWithTask {
158 | defer {
159 | expectation.fulfill()
160 | }
161 | throw CancelledError()
162 | }
163 | waitForTestExpectations()
164 | XCTAssertTrue(task.cancelled)
165 | XCTAssertNil(task.error)
166 | }
167 |
168 | // MARK: Continuations
169 |
170 | func testContinueWithOnSucessfulTaskByReturningResult() {
171 | let expectation = self.expectation(description: name)
172 | let initialTask = Task(1)
173 |
174 | let continuationTask = initialTask.continueWith { task -> String? in
175 | XCTAssertTrue(task === initialTask)
176 | return self.name
177 | }
178 |
179 | continuationTask.continueOnSuccessWith {
180 | XCTAssertEqual($0, self.name)
181 | expectation.fulfill()
182 | }
183 | waitForTestExpectations()
184 | }
185 |
186 | func testContinueWithOnErroredTaskByReturningResult() {
187 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
188 | let expectation = self.expectation(description: name)
189 | let initialTask = Task(error: error)
190 |
191 | let continuationTask = initialTask.continueWith { task -> String? in
192 | XCTAssertTrue(task === initialTask)
193 | return self.name
194 | }
195 |
196 | continuationTask.continueOnSuccessWith {
197 | XCTAssertEqual($0, self.name)
198 | expectation.fulfill()
199 | }
200 | waitForTestExpectations()
201 | }
202 |
203 | func testContinueWithOnCancelledTaskByReturningResult() {
204 | let expectation = self.expectation(description: name)
205 | let initialTask = Task.cancelledTask()
206 |
207 | let continuationTask = initialTask.continueWith { task -> String? in
208 | XCTAssertTrue(task === initialTask)
209 | return self.name
210 | }
211 |
212 | continuationTask.continueOnSuccessWith {
213 | XCTAssertEqual($0, self.name)
214 | expectation.fulfill()
215 | }
216 | waitForTestExpectations()
217 | }
218 |
219 | func testContinueWithWithExecutor() {
220 | let expectation = self.expectation(description: name)
221 | let initialTask = Task.cancelledTask()
222 | let executorExpectation = self.expectation(description: "executor")
223 |
224 | let executor = Executor.closure {
225 | $0()
226 | executorExpectation.fulfill()
227 | }
228 |
229 | let continuationTask = initialTask.continueWith(executor) { task -> String? in
230 | XCTAssertTrue(task === initialTask)
231 | return self.name
232 | }
233 |
234 | continuationTask.continueOnSuccessWith {
235 | XCTAssertEqual($0, self.name)
236 | expectation.fulfill()
237 | }
238 | waitForTestExpectations()
239 | }
240 |
241 | func testContinueWithByReturningNilResult() {
242 | let expectation = self.expectation(description: name)
243 | let initialTask = Task(1)
244 |
245 | let continuationTask = initialTask.continueWith { task -> String? in
246 | XCTAssertTrue(task === initialTask)
247 | return nil
248 | }
249 |
250 | continuationTask.continueOnSuccessWith {
251 | XCTAssertNil($0)
252 | expectation.fulfill()
253 | }
254 | waitForTestExpectations()
255 | }
256 |
257 | func testContinueWithByReturningTask() {
258 | let expectation = self.expectation(description: name)
259 | let firstTask = Task(1)
260 | let secondTask = Task(name)
261 |
262 | let continuationTask = firstTask.continueWithTask { task -> Task in
263 | XCTAssertTrue(task === firstTask)
264 | return secondTask
265 | }
266 |
267 | XCTAssertTrue(continuationTask !== secondTask)
268 | continuationTask.continueOnSuccessWith {
269 | XCTAssertEqual($0, self.name)
270 | expectation.fulfill()
271 | }
272 | waitForTestExpectations()
273 | }
274 |
275 | func testContinueWithByReturningNilTask() {
276 | let expectation = self.expectation(description: name)
277 | let initialTask = Task(1)
278 |
279 | let continuationTask = initialTask.continueWith { task in
280 | XCTAssertTrue(task === initialTask)
281 | }
282 |
283 | continuationTask.continueWith { _ in
284 | expectation.fulfill()
285 | }
286 | waitForTestExpectations()
287 | }
288 |
289 | func testChainedContinueWithFunctions() {
290 | let expectation = self.expectation(description: name)
291 | var count = 0
292 |
293 | Task.cancelledTask().continueWith { _ -> String? in
294 | count += 1
295 | XCTAssertEqual(count, 1)
296 | return nil
297 | }.continueWith { _ -> String? in
298 | count += 1
299 | XCTAssertEqual(count, 2)
300 | return nil
301 | }.continueWith { _ -> String? in
302 | count += 1
303 | XCTAssertEqual(count, 3)
304 | return nil
305 | }.continueWith { _ -> String? in
306 | count += 1
307 | XCTAssertEqual(count, 4)
308 | return nil
309 | }.continueWith { _ -> String? in
310 | count += 1
311 | XCTAssertEqual(count, 5)
312 | expectation.fulfill()
313 | return nil
314 | }
315 |
316 | waitForTestExpectations()
317 | }
318 |
319 | func testChainedContinueWithWithAsyncExecutor() {
320 | let expectation = self.expectation(description: name)
321 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
322 | var count = 0
323 |
324 | Task.cancelledTask().continueWith(executor) { _ in
325 | count += 1
326 | XCTAssertEqual(count, 1)
327 | }.continueWith(executor) { _ in
328 | count += 1
329 | XCTAssertEqual(count, 2)
330 | }.continueWith(executor) { _ in
331 | count += 1
332 | XCTAssertEqual(count, 3)
333 | }.continueWith(executor) { _ in
334 | count += 1
335 | XCTAssertEqual(count, 4)
336 | }.continueWith(executor) { _ in
337 | count += 1
338 | XCTAssertEqual(count, 5)
339 | expectation.fulfill()
340 | }
341 |
342 | waitForTestExpectations()
343 | }
344 |
345 | //--------------------------------------
346 | // MARK: - continueOnError
347 | //--------------------------------------
348 |
349 | func testContinueOnGenericErrorRecovers() {
350 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
351 | let expectation = self.expectation(description: name)
352 | let initialTask = Task(error: error)
353 |
354 | let continuationTask = initialTask.continueOnErrorWith { taskError -> String? in
355 | XCTAssertEqual(taskError as NSError, error)
356 | return self.name
357 | }
358 | continuationTask.continueOnSuccessWith {
359 | XCTAssertEqual($0, self.name)
360 | expectation.fulfill()
361 | }
362 | waitForTestExpectations()
363 | }
364 |
365 | func testContinueOnSpecificErrorRecovers() {
366 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
367 | let expectation = self.expectation(description: name)
368 | let initialTask = Task(error: error)
369 |
370 | let continuationTask = initialTask.continueOnErrorWith { (taskError: NSError) -> String? in
371 | XCTAssertEqual(taskError, error)
372 | return self.name
373 | }
374 | continuationTask.continueOnSuccessWith {
375 | XCTAssertEqual($0, self.name)
376 | expectation.fulfill()
377 | }
378 | waitForTestExpectations()
379 | }
380 |
381 | //--------------------------------------
382 | // MARK: - WhenAll
383 | //--------------------------------------
384 |
385 | func testWhenAllTasksEmptyArray() {
386 | let tasks: [Task] = []
387 |
388 | let expectation = self.expectation(description: name)
389 | Task.whenAll(tasks).continueWith { task in
390 | XCTAssertTrue(task.completed)
391 | XCTAssertFalse(task.faulted)
392 | XCTAssertFalse(task.cancelled)
393 | expectation.fulfill()
394 | }
395 | waitForExpectations(timeout: 5.0, handler: nil)
396 | }
397 |
398 | func testWhenAllTasksSuccess() {
399 | var tasks = [Task]()
400 | var count: Int32 = 0
401 |
402 | for i in 1...20 {
403 | let task = Task.withDelay(0.5)
404 | .continueWith(continuation: { _ -> Int in
405 | OSAtomicIncrement32(&count)
406 | return i
407 | })
408 | tasks.append(task)
409 | }
410 |
411 | let expectation = self.expectation(description: name)
412 | let task = Task.whenAll(tasks).continueWith { task in
413 | XCTAssertEqual(count, Int32(tasks.count))
414 | XCTAssertTrue(task.completed)
415 | XCTAssertFalse(task.faulted)
416 | XCTAssertFalse(task.cancelled)
417 | expectation.fulfill()
418 | }
419 |
420 | XCTAssertFalse(task.completed)
421 | XCTAssertFalse(task.faulted)
422 | XCTAssertFalse(task.cancelled)
423 |
424 | waitForExpectations(timeout: 5.0, handler: nil)
425 | }
426 |
427 | func testWhenAllTasksWithResultSuccess() {
428 | var tasks = [Task]()
429 | var count: Int32 = 0
430 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
431 |
432 | for i in 1...20 {
433 | let task = Task.withDelay(0.5)
434 | .continueWith(executor, continuation: { _ -> Int in
435 | OSAtomicIncrement32(&count)
436 | return i
437 | })
438 | tasks.append(task)
439 | }
440 |
441 | let expectation = self.expectation(description: name)
442 | let task = Task.whenAllResult(tasks).continueWith { task in
443 | XCTAssertEqual(count, Int32(tasks.count))
444 | XCTAssertTrue(task.completed)
445 | XCTAssertFalse(task.faulted)
446 | XCTAssertFalse(task.cancelled)
447 | XCTAssertEqual(Int32(task.result!.count), count)
448 | expectation.fulfill()
449 | }
450 |
451 | XCTAssertFalse(task.completed)
452 | XCTAssertFalse(task.faulted)
453 | XCTAssertFalse(task.cancelled)
454 |
455 | waitForTestExpectations()
456 | }
457 |
458 | func testWhenAllTasksWithCancel() {
459 | var tasks = [Task]()
460 | var count: Int32 = 0
461 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
462 |
463 | for i in 1...20 {
464 | let task = Task.withDelay(0.5)
465 | .continueWithTask(executor, continuation: { _ -> Task in
466 | OSAtomicIncrement32(&count)
467 | if i == 20 {
468 | return Task.cancelledTask()
469 | }
470 | return Task(i)
471 | })
472 | tasks.append(task)
473 | }
474 |
475 | let expectation = self.expectation(description: name)
476 | let task = Task.whenAllResult(tasks).continueWith { task in
477 | XCTAssertEqual(count, Int32(tasks.count))
478 | XCTAssertTrue(task.completed)
479 | XCTAssertFalse(task.faulted)
480 | XCTAssertTrue(task.cancelled)
481 | expectation.fulfill()
482 | }
483 |
484 | XCTAssertFalse(task.completed)
485 | XCTAssertFalse(task.faulted)
486 | XCTAssertFalse(task.cancelled)
487 |
488 | waitForTestExpectations()
489 | }
490 |
491 | func testWhenAllTasksError() {
492 | var tasks: [Task] = []
493 | var count: Int32 = 0
494 |
495 | for i in 1...20 {
496 | let task = Task.withDelay(0.5)
497 | .continueWith(continuation: { _ in
498 | OSAtomicIncrement32(&count)
499 | throw NSError(domain: "bolts", code: i, userInfo: nil)
500 | })
501 | tasks.append(task)
502 | }
503 |
504 | let expectation = self.expectation(description: name)
505 | let task = Task.whenAll(tasks).continueWith { task in
506 | XCTAssertEqual(count, Int32(tasks.count))
507 | XCTAssertTrue(task.completed)
508 | XCTAssertTrue(task.faulted)
509 | XCTAssertFalse(task.cancelled)
510 | guard let error = task.error as? AggregateError else {
511 | XCTFail("Not an aggregate error returned.")
512 | expectation.fulfill()
513 | return
514 | }
515 | XCTAssertEqual(error.errors.count, Int(count))
516 | expectation.fulfill()
517 | }
518 |
519 | XCTAssertFalse(task.completed)
520 | XCTAssertFalse(task.faulted)
521 | XCTAssertFalse(task.cancelled)
522 |
523 | waitForExpectations(timeout: 5.0, handler: nil)
524 | }
525 |
526 | // MARK: When Any
527 |
528 | func testWhenAnyTasksSuccess() {
529 | var tasks = [Task]()
530 | var count: Int32 = 0
531 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
532 |
533 | tasks.append(Task.withDelay(0.2).continueWith { _ in
534 | // Use max value of Int32, so we can use the same code across both 32 and 64 bit archs.
535 | return Int(arc4random_uniform(UInt32(Int32.max)))
536 | })
537 | for i in 1...20 {
538 | let task = Task.withDelay(0.5)
539 | .continueWith(executor, continuation: { _ -> Int in
540 | OSAtomicIncrement32(&count)
541 | return i
542 | })
543 | tasks.append(task)
544 | }
545 |
546 | let expectation = self.expectation(description: name)
547 | let task = Task.whenAny(tasks).continueWith { task in
548 | XCTAssertNotEqual(count, Int32(tasks.count))
549 | XCTAssertTrue(task.completed)
550 | XCTAssertFalse(task.faulted)
551 | XCTAssertFalse(task.cancelled)
552 | expectation.fulfill()
553 | }
554 |
555 | XCTAssertFalse(task.completed)
556 | XCTAssertFalse(task.faulted)
557 | XCTAssertFalse(task.cancelled)
558 |
559 | waitForTestExpectations()
560 | }
561 |
562 | func testWhenAnyTasksWithErrors() {
563 | var tasks = [Task]()
564 | var count: Int32 = 0
565 |
566 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
567 | let error = NSError(domain: "com.bolts", code: 1, userInfo: nil)
568 |
569 | for i in 1...20 {
570 | let task = Task.withDelay(Double(i) * 0.5)
571 | .continueWithTask(executor, continuation: { _ -> Task in
572 | OSAtomicIncrement32(&count)
573 | return Task(error: error)
574 | })
575 | tasks.append(task)
576 | }
577 |
578 | let expectation = self.expectation(description: name)
579 | let task = Task.whenAny(tasks).continueWith { task in
580 | XCTAssertNotEqual(count, Int32(tasks.count))
581 | XCTAssertTrue(task.completed)
582 | XCTAssertFalse(task.faulted)
583 | XCTAssertFalse(task.cancelled)
584 | expectation.fulfill()
585 | }
586 |
587 | XCTAssertFalse(task.completed)
588 | XCTAssertFalse(task.faulted)
589 | XCTAssertFalse(task.cancelled)
590 |
591 | waitForTestExpectations()
592 | }
593 |
594 | func testWhenAnyTasksWithCancel() {
595 | var tasks = [Task]()
596 | var count: Int32 = 0
597 |
598 | let executor = Executor.queue(DispatchQueue.global(qos: .default))
599 |
600 | for i in 1...20 {
601 | let task = Task.withDelay(Double(i) * 0.5)
602 | .continueWithTask(executor, continuation: { _ -> Task in
603 | OSAtomicIncrement32(&count)
604 | return Task.cancelledTask()
605 | })
606 | tasks.append(task)
607 | }
608 |
609 | let expectation = self.expectation(description: name)
610 | let task = Task.whenAny(tasks).continueWith { task in
611 | XCTAssertNotEqual(count, Int32(tasks.count))
612 | XCTAssertTrue(task.completed)
613 | XCTAssertFalse(task.faulted)
614 | XCTAssertFalse(task.cancelled)
615 | expectation.fulfill()
616 | }
617 |
618 | XCTAssertFalse(task.completed)
619 | XCTAssertFalse(task.faulted)
620 | XCTAssertFalse(task.cancelled)
621 |
622 | waitForTestExpectations()
623 | }
624 |
625 | // MARK: Wait
626 |
627 | func testTaskWait() {
628 | Task.withDelay(0.5).waitUntilCompleted()
629 | }
630 |
631 | func testCompletedTaskWait() {
632 | Task(self.name).waitUntilCompleted()
633 | }
634 |
635 | func testTaskChainWait() {
636 | var count = 0
637 |
638 | Task.cancelledTask().continueWith { _ in
639 | count += 1
640 | XCTAssertEqual(count, 1)
641 | }.continueWith { _ in
642 | count += 1
643 | XCTAssertEqual(count, 2)
644 | }.continueWith { _ in
645 | count += 1
646 | XCTAssertEqual(count, 3)
647 | }.continueWith { _ in
648 | count += 1
649 | XCTAssertEqual(count, 4)
650 | }.continueWith { _ in
651 | count += 1
652 | XCTAssertEqual(count, 5)
653 | }.waitUntilCompleted()
654 | XCTAssertEqual(count, 5)
655 | }
656 | }
657 |
--------------------------------------------------------------------------------
/BoltsSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 065894EF1C9A9391000FDDA6 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300651C93AF7300E1A1ED /* Task.swift */; };
11 | 065894F01C9A9391000FDDA6 /* TaskCompletionSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */; };
12 | 065894F11C9A9391000FDDA6 /* Executor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300641C93AF7300E1A1ED /* Executor.swift */; };
13 | 065894F21C9A9391000FDDA6 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300631C93AF7300E1A1ED /* Errors.swift */; };
14 | 065894F51C9A93B7000FDDA6 /* Executor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300641C93AF7300E1A1ED /* Executor.swift */; };
15 | 065894F61C9A93B7000FDDA6 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300651C93AF7300E1A1ED /* Task.swift */; };
16 | 065894F71C9A93B7000FDDA6 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300631C93AF7300E1A1ED /* Errors.swift */; };
17 | 065894F81C9A93B7000FDDA6 /* TaskCompletionSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */; };
18 | 065895121C9A947B000FDDA6 /* ExecutorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300751C93AF9F00E1A1ED /* ExecutorTests.swift */; };
19 | 065895131C9A947B000FDDA6 /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300781C93AF9F00E1A1ED /* TaskTests.swift */; };
20 | 065895141C9A947B000FDDA6 /* TaskCompletionSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300771C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift */; };
21 | 0658951F1C9A9496000FDDA6 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 065894FF1C9A93B7000FDDA6 /* BoltsSwift.framework */; };
22 | 810AB3201C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 810AB31F1C9B1AC3005B6184 /* XCTestCase+TestName.swift */; };
23 | 810AB3211C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 810AB31F1C9B1AC3005B6184 /* XCTestCase+TestName.swift */; };
24 | 810AB3221C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 810AB31F1C9B1AC3005B6184 /* XCTestCase+TestName.swift */; };
25 | 81CC14F71A9BE0A100B28F86 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 81CC14EC1A9BE0A100B28F86 /* BoltsSwift.framework */; };
26 | 81D300681C93AF7300E1A1ED /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300631C93AF7300E1A1ED /* Errors.swift */; };
27 | 81D300691C93AF7300E1A1ED /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300631C93AF7300E1A1ED /* Errors.swift */; };
28 | 81D3006A1C93AF7300E1A1ED /* Executor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300641C93AF7300E1A1ED /* Executor.swift */; };
29 | 81D3006B1C93AF7300E1A1ED /* Executor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300641C93AF7300E1A1ED /* Executor.swift */; };
30 | 81D3006C1C93AF7300E1A1ED /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300651C93AF7300E1A1ED /* Task.swift */; };
31 | 81D3006D1C93AF7300E1A1ED /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300651C93AF7300E1A1ED /* Task.swift */; };
32 | 81D3006E1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */; };
33 | 81D3006F1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */; };
34 | 81D300791C93AF9F00E1A1ED /* ExecutorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300751C93AF9F00E1A1ED /* ExecutorTests.swift */; };
35 | 81D3007A1C93AF9F00E1A1ED /* ExecutorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300751C93AF9F00E1A1ED /* ExecutorTests.swift */; };
36 | 81D3007D1C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300771C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift */; };
37 | 81D3007E1C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300771C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift */; };
38 | 81D3007F1C93AF9F00E1A1ED /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300781C93AF9F00E1A1ED /* TaskTests.swift */; };
39 | 81D300801C93AF9F00E1A1ED /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D300781C93AF9F00E1A1ED /* TaskTests.swift */; };
40 | 87FEF3721A9085FA00C60678 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 87FEF3661A9085FA00C60678 /* BoltsSwift.framework */; };
41 | F569C0C11CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
42 | F569C0C21CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
43 | F569C0C31CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
44 | F569C0C41CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */; };
45 | F569C0CC1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
46 | F569C0CD1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
47 | F569C0CE1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
48 | F569C0CF1CFF6AEE000749B6 /* Task+Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */; };
49 | F569C0D71CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
50 | F569C0D81CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
51 | F569C0D91CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
52 | F569C0DA1CFF6B18000749B6 /* Task+WhenAll.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */; };
53 | F569C0E11CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
54 | F569C0E21CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
55 | F569C0E31CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
56 | F569C0E41CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */; };
57 | /* End PBXBuildFile section */
58 |
59 | /* Begin PBXContainerItemProxy section */
60 | 0658951D1C9A948E000FDDA6 /* PBXContainerItemProxy */ = {
61 | isa = PBXContainerItemProxy;
62 | containerPortal = 87FEF35D1A9085FA00C60678 /* Project object */;
63 | proxyType = 1;
64 | remoteGlobalIDString = 065894F31C9A93B7000FDDA6;
65 | remoteInfo = "BoltsSwift-tvOS";
66 | };
67 | 81CC14F81A9BE0A100B28F86 /* PBXContainerItemProxy */ = {
68 | isa = PBXContainerItemProxy;
69 | containerPortal = 87FEF35D1A9085FA00C60678 /* Project object */;
70 | proxyType = 1;
71 | remoteGlobalIDString = 81CC14EB1A9BE0A100B28F86;
72 | remoteInfo = "Bolts-Mac";
73 | };
74 | 87FEF3731A9085FA00C60678 /* PBXContainerItemProxy */ = {
75 | isa = PBXContainerItemProxy;
76 | containerPortal = 87FEF35D1A9085FA00C60678 /* Project object */;
77 | proxyType = 1;
78 | remoteGlobalIDString = 87FEF3651A9085FA00C60678;
79 | remoteInfo = Bolts;
80 | };
81 | /* End PBXContainerItemProxy section */
82 |
83 | /* Begin PBXFileReference section */
84 | 065894E71C9A933B000FDDA6 /* BoltsSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoltsSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
85 | 065894FF1C9A93B7000FDDA6 /* BoltsSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoltsSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
86 | 0658951B1C9A947B000FDDA6 /* BoltsSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BoltsSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
87 | 81059E4C233EE56E00DE20C1 /* BoltsSwift-Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwift-Shared.xcconfig"; sourceTree = ""; };
88 | 81059E4D233EE61F00DE20C1 /* BoltsSwiftTests-Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwiftTests-Shared.xcconfig"; sourceTree = ""; };
89 | 810AB31F1C9B1AC3005B6184 /* XCTestCase+TestName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+TestName.swift"; sourceTree = ""; };
90 | 812DB5271D3597BF00552C9F /* BoltsSwift-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwift-iOS.xcconfig"; sourceTree = ""; };
91 | 812DB5281D3597BF00552C9F /* BoltsSwift-macOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwift-macOS.xcconfig"; sourceTree = ""; };
92 | 812DB5291D3597BF00552C9F /* BoltsSwift-tvOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwift-tvOS.xcconfig"; sourceTree = ""; };
93 | 812DB52A1D3597BF00552C9F /* BoltsSwift-watchOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwift-watchOS.xcconfig"; sourceTree = ""; };
94 | 812DB52B1D3597BF00552C9F /* BoltsSwiftTests-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwiftTests-iOS.xcconfig"; sourceTree = ""; };
95 | 812DB52C1D3597BF00552C9F /* BoltsSwiftTests-macOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwiftTests-macOS.xcconfig"; sourceTree = ""; };
96 | 812DB52D1D3597BF00552C9F /* BoltsSwiftTests-tvOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "BoltsSwiftTests-tvOS.xcconfig"; sourceTree = ""; };
97 | 812DB52F1D3597BF00552C9F /* Common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Common.xcconfig; sourceTree = ""; };
98 | 812DB5311D3597BF00552C9F /* iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = iOS.xcconfig; sourceTree = ""; };
99 | 812DB5321D3597BF00552C9F /* macOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = macOS.xcconfig; sourceTree = ""; };
100 | 812DB5331D3597BF00552C9F /* tvOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = tvOS.xcconfig; sourceTree = ""; };
101 | 812DB5341D3597BF00552C9F /* watchOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = watchOS.xcconfig; sourceTree = ""; };
102 | 812DB5361D3597BF00552C9F /* Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Application.xcconfig; sourceTree = ""; };
103 | 812DB5371D3597BF00552C9F /* DynamicFramework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DynamicFramework.xcconfig; sourceTree = ""; };
104 | 812DB5381D3597BF00552C9F /* LogicTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = LogicTests.xcconfig; sourceTree = ""; };
105 | 812DB5391D3597BF00552C9F /* StaticFramework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = StaticFramework.xcconfig; sourceTree = ""; };
106 | 812DB53B1D3597BF00552C9F /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
107 | 812DB53C1D3597BF00552C9F /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
108 | 812DB53D1D3597BF00552C9F /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
109 | 818DECFF233EED9700EABA07 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
110 | 81951A901D46BA2F00958108 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; };
111 | 81CC14EC1A9BE0A100B28F86 /* BoltsSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoltsSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
112 | 81CC14F61A9BE0A100B28F86 /* BoltsSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BoltsSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
113 | 81D300631C93AF7300E1A1ED /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; };
114 | 81D300641C93AF7300E1A1ED /* Executor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Executor.swift; sourceTree = ""; };
115 | 81D300651C93AF7300E1A1ED /* Task.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; };
116 | 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskCompletionSource.swift; sourceTree = ""; };
117 | 81D300671C93AF7300E1A1ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
118 | 81D300751C93AF9F00E1A1ED /* ExecutorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExecutorTests.swift; sourceTree = ""; };
119 | 81D300761C93AF9F00E1A1ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
120 | 81D300771C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskCompletionSourceTests.swift; sourceTree = ""; };
121 | 81D300781C93AF9F00E1A1ED /* TaskTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskTests.swift; sourceTree = ""; };
122 | 87FEF3661A9085FA00C60678 /* BoltsSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BoltsSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
123 | 87FEF3711A9085FA00C60678 /* BoltsSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BoltsSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
124 | F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+ContinueWith.swift"; sourceTree = ""; };
125 | F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+Delay.swift"; sourceTree = ""; };
126 | F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+WhenAll.swift"; sourceTree = ""; };
127 | F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Task+WhenAny.swift"; sourceTree = ""; };
128 | /* End PBXFileReference section */
129 |
130 | /* Begin PBXFrameworksBuildPhase section */
131 | 065894E31C9A933B000FDDA6 /* Frameworks */ = {
132 | isa = PBXFrameworksBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | 065894F91C9A93B7000FDDA6 /* Frameworks */ = {
139 | isa = PBXFrameworksBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | );
143 | runOnlyForDeploymentPostprocessing = 0;
144 | };
145 | 065895151C9A947B000FDDA6 /* Frameworks */ = {
146 | isa = PBXFrameworksBuildPhase;
147 | buildActionMask = 2147483647;
148 | files = (
149 | 0658951F1C9A9496000FDDA6 /* BoltsSwift.framework in Frameworks */,
150 | );
151 | runOnlyForDeploymentPostprocessing = 0;
152 | };
153 | 81CC14E81A9BE0A100B28F86 /* Frameworks */ = {
154 | isa = PBXFrameworksBuildPhase;
155 | buildActionMask = 2147483647;
156 | files = (
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | 81CC14F31A9BE0A100B28F86 /* Frameworks */ = {
161 | isa = PBXFrameworksBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | 81CC14F71A9BE0A100B28F86 /* BoltsSwift.framework in Frameworks */,
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | 87FEF3621A9085FA00C60678 /* Frameworks */ = {
169 | isa = PBXFrameworksBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | );
173 | runOnlyForDeploymentPostprocessing = 0;
174 | };
175 | 87FEF36E1A9085FA00C60678 /* Frameworks */ = {
176 | isa = PBXFrameworksBuildPhase;
177 | buildActionMask = 2147483647;
178 | files = (
179 | 87FEF3721A9085FA00C60678 /* BoltsSwift.framework in Frameworks */,
180 | );
181 | runOnlyForDeploymentPostprocessing = 0;
182 | };
183 | /* End PBXFrameworksBuildPhase section */
184 |
185 | /* Begin PBXGroup section */
186 | 812DB5261D3597BF00552C9F /* Configurations */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 81059E4C233EE56E00DE20C1 /* BoltsSwift-Shared.xcconfig */,
190 | 812DB5271D3597BF00552C9F /* BoltsSwift-iOS.xcconfig */,
191 | 812DB5281D3597BF00552C9F /* BoltsSwift-macOS.xcconfig */,
192 | 812DB5291D3597BF00552C9F /* BoltsSwift-tvOS.xcconfig */,
193 | 812DB52A1D3597BF00552C9F /* BoltsSwift-watchOS.xcconfig */,
194 | 81059E4D233EE61F00DE20C1 /* BoltsSwiftTests-Shared.xcconfig */,
195 | 812DB52B1D3597BF00552C9F /* BoltsSwiftTests-iOS.xcconfig */,
196 | 812DB52C1D3597BF00552C9F /* BoltsSwiftTests-macOS.xcconfig */,
197 | 812DB52D1D3597BF00552C9F /* BoltsSwiftTests-tvOS.xcconfig */,
198 | 81951A901D46BA2F00958108 /* Version.xcconfig */,
199 | 812DB52E1D3597BF00552C9F /* Shared */,
200 | );
201 | path = Configurations;
202 | sourceTree = "";
203 | };
204 | 812DB52E1D3597BF00552C9F /* Shared */ = {
205 | isa = PBXGroup;
206 | children = (
207 | 812DB52F1D3597BF00552C9F /* Common.xcconfig */,
208 | 812DB5301D3597BF00552C9F /* Platform */,
209 | 812DB5351D3597BF00552C9F /* Product */,
210 | 812DB53A1D3597BF00552C9F /* Project */,
211 | 812DB53D1D3597BF00552C9F /* Warnings.xcconfig */,
212 | );
213 | path = Shared;
214 | sourceTree = "";
215 | };
216 | 812DB5301D3597BF00552C9F /* Platform */ = {
217 | isa = PBXGroup;
218 | children = (
219 | 812DB5311D3597BF00552C9F /* iOS.xcconfig */,
220 | 812DB5321D3597BF00552C9F /* macOS.xcconfig */,
221 | 812DB5331D3597BF00552C9F /* tvOS.xcconfig */,
222 | 812DB5341D3597BF00552C9F /* watchOS.xcconfig */,
223 | );
224 | path = Platform;
225 | sourceTree = "";
226 | };
227 | 812DB5351D3597BF00552C9F /* Product */ = {
228 | isa = PBXGroup;
229 | children = (
230 | 812DB5361D3597BF00552C9F /* Application.xcconfig */,
231 | 812DB5371D3597BF00552C9F /* DynamicFramework.xcconfig */,
232 | 812DB5381D3597BF00552C9F /* LogicTests.xcconfig */,
233 | 812DB5391D3597BF00552C9F /* StaticFramework.xcconfig */,
234 | );
235 | path = Product;
236 | sourceTree = "";
237 | };
238 | 812DB53A1D3597BF00552C9F /* Project */ = {
239 | isa = PBXGroup;
240 | children = (
241 | 812DB53B1D3597BF00552C9F /* Debug.xcconfig */,
242 | 812DB53C1D3597BF00552C9F /* Release.xcconfig */,
243 | );
244 | path = Project;
245 | sourceTree = "";
246 | };
247 | 81D300611C93AF7300E1A1ED /* Sources */ = {
248 | isa = PBXGroup;
249 | children = (
250 | 818DECFF233EED9700EABA07 /* Package.swift */,
251 | 81D300621C93AF7300E1A1ED /* BoltsSwift */,
252 | 81D300731C93AF8C00E1A1ED /* Supporting Files */,
253 | );
254 | path = Sources;
255 | sourceTree = "";
256 | };
257 | 81D300621C93AF7300E1A1ED /* BoltsSwift */ = {
258 | isa = PBXGroup;
259 | children = (
260 | 81D300651C93AF7300E1A1ED /* Task.swift */,
261 | 81D300661C93AF7300E1A1ED /* TaskCompletionSource.swift */,
262 | F569C0C01CFF6A07000749B6 /* Task+ContinueWith.swift */,
263 | F569C0CB1CFF6AEE000749B6 /* Task+Delay.swift */,
264 | F569C0D61CFF6B18000749B6 /* Task+WhenAll.swift */,
265 | F569C0E01CFF6B1F000749B6 /* Task+WhenAny.swift */,
266 | 81D300641C93AF7300E1A1ED /* Executor.swift */,
267 | 81D300631C93AF7300E1A1ED /* Errors.swift */,
268 | );
269 | path = BoltsSwift;
270 | sourceTree = "";
271 | };
272 | 81D300731C93AF8C00E1A1ED /* Supporting Files */ = {
273 | isa = PBXGroup;
274 | children = (
275 | 81D300671C93AF7300E1A1ED /* Info.plist */,
276 | );
277 | name = "Supporting Files";
278 | sourceTree = "";
279 | };
280 | 81D300741C93AF9F00E1A1ED /* Tests */ = {
281 | isa = PBXGroup;
282 | children = (
283 | 81D300781C93AF9F00E1A1ED /* TaskTests.swift */,
284 | 81D300771C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift */,
285 | 81D300751C93AF9F00E1A1ED /* ExecutorTests.swift */,
286 | 810AB31F1C9B1AC3005B6184 /* XCTestCase+TestName.swift */,
287 | 81D300811C93AFA600E1A1ED /* Supporting Files */,
288 | );
289 | path = Tests;
290 | sourceTree = "";
291 | };
292 | 81D300811C93AFA600E1A1ED /* Supporting Files */ = {
293 | isa = PBXGroup;
294 | children = (
295 | 81D300761C93AF9F00E1A1ED /* Info.plist */,
296 | );
297 | name = "Supporting Files";
298 | sourceTree = "";
299 | };
300 | 87FEF35C1A9085FA00C60678 = {
301 | isa = PBXGroup;
302 | children = (
303 | 812DB5261D3597BF00552C9F /* Configurations */,
304 | 81D300611C93AF7300E1A1ED /* Sources */,
305 | 81D300741C93AF9F00E1A1ED /* Tests */,
306 | 87FEF3671A9085FA00C60678 /* Products */,
307 | );
308 | indentWidth = 4;
309 | sourceTree = "";
310 | tabWidth = 4;
311 | };
312 | 87FEF3671A9085FA00C60678 /* Products */ = {
313 | isa = PBXGroup;
314 | children = (
315 | 87FEF3661A9085FA00C60678 /* BoltsSwift.framework */,
316 | 87FEF3711A9085FA00C60678 /* BoltsSwiftTests.xctest */,
317 | 81CC14EC1A9BE0A100B28F86 /* BoltsSwift.framework */,
318 | 81CC14F61A9BE0A100B28F86 /* BoltsSwiftTests.xctest */,
319 | 065894E71C9A933B000FDDA6 /* BoltsSwift.framework */,
320 | 065894FF1C9A93B7000FDDA6 /* BoltsSwift.framework */,
321 | 0658951B1C9A947B000FDDA6 /* BoltsSwiftTests.xctest */,
322 | );
323 | name = Products;
324 | sourceTree = "";
325 | };
326 | /* End PBXGroup section */
327 |
328 | /* Begin PBXHeadersBuildPhase section */
329 | 065894E41C9A933B000FDDA6 /* Headers */ = {
330 | isa = PBXHeadersBuildPhase;
331 | buildActionMask = 2147483647;
332 | files = (
333 | );
334 | runOnlyForDeploymentPostprocessing = 0;
335 | };
336 | 065894FA1C9A93B7000FDDA6 /* Headers */ = {
337 | isa = PBXHeadersBuildPhase;
338 | buildActionMask = 2147483647;
339 | files = (
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | 81CC14E91A9BE0A100B28F86 /* Headers */ = {
344 | isa = PBXHeadersBuildPhase;
345 | buildActionMask = 2147483647;
346 | files = (
347 | );
348 | runOnlyForDeploymentPostprocessing = 0;
349 | };
350 | 87FEF3631A9085FA00C60678 /* Headers */ = {
351 | isa = PBXHeadersBuildPhase;
352 | buildActionMask = 2147483647;
353 | files = (
354 | );
355 | runOnlyForDeploymentPostprocessing = 0;
356 | };
357 | /* End PBXHeadersBuildPhase section */
358 |
359 | /* Begin PBXNativeTarget section */
360 | 065894E61C9A933B000FDDA6 /* BoltsSwift-watchOS */ = {
361 | isa = PBXNativeTarget;
362 | buildConfigurationList = 065894EE1C9A933B000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwift-watchOS" */;
363 | buildPhases = (
364 | 065894E21C9A933B000FDDA6 /* Sources */,
365 | 065894E31C9A933B000FDDA6 /* Frameworks */,
366 | 065894E41C9A933B000FDDA6 /* Headers */,
367 | 065894E51C9A933B000FDDA6 /* Resources */,
368 | );
369 | buildRules = (
370 | );
371 | dependencies = (
372 | );
373 | name = "BoltsSwift-watchOS";
374 | productName = "BoltsSwift-watchOS";
375 | productReference = 065894E71C9A933B000FDDA6 /* BoltsSwift.framework */;
376 | productType = "com.apple.product-type.framework";
377 | };
378 | 065894F31C9A93B7000FDDA6 /* BoltsSwift-tvOS */ = {
379 | isa = PBXNativeTarget;
380 | buildConfigurationList = 065894FC1C9A93B7000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwift-tvOS" */;
381 | buildPhases = (
382 | 065894F41C9A93B7000FDDA6 /* Sources */,
383 | 065894F91C9A93B7000FDDA6 /* Frameworks */,
384 | 065894FA1C9A93B7000FDDA6 /* Headers */,
385 | 065894FB1C9A93B7000FDDA6 /* Resources */,
386 | );
387 | buildRules = (
388 | );
389 | dependencies = (
390 | );
391 | name = "BoltsSwift-tvOS";
392 | productName = Bolts;
393 | productReference = 065894FF1C9A93B7000FDDA6 /* BoltsSwift.framework */;
394 | productType = "com.apple.product-type.framework";
395 | };
396 | 0658950E1C9A947B000FDDA6 /* BoltsSwiftTests-tvOS */ = {
397 | isa = PBXNativeTarget;
398 | buildConfigurationList = 065895181C9A947B000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-tvOS" */;
399 | buildPhases = (
400 | 065895111C9A947B000FDDA6 /* Sources */,
401 | 065895151C9A947B000FDDA6 /* Frameworks */,
402 | 065895171C9A947B000FDDA6 /* Resources */,
403 | );
404 | buildRules = (
405 | );
406 | dependencies = (
407 | 0658951E1C9A948E000FDDA6 /* PBXTargetDependency */,
408 | );
409 | name = "BoltsSwiftTests-tvOS";
410 | productName = BoltsTests;
411 | productReference = 0658951B1C9A947B000FDDA6 /* BoltsSwiftTests.xctest */;
412 | productType = "com.apple.product-type.bundle.unit-test";
413 | };
414 | 81CC14EB1A9BE0A100B28F86 /* BoltsSwift-macOS */ = {
415 | isa = PBXNativeTarget;
416 | buildConfigurationList = 81CC14FF1A9BE0A100B28F86 /* Build configuration list for PBXNativeTarget "BoltsSwift-macOS" */;
417 | buildPhases = (
418 | 81CC14E71A9BE0A100B28F86 /* Sources */,
419 | 81CC14E81A9BE0A100B28F86 /* Frameworks */,
420 | 81CC14E91A9BE0A100B28F86 /* Headers */,
421 | 81CC14EA1A9BE0A100B28F86 /* Resources */,
422 | );
423 | buildRules = (
424 | );
425 | dependencies = (
426 | );
427 | name = "BoltsSwift-macOS";
428 | productName = "Bolts-Mac";
429 | productReference = 81CC14EC1A9BE0A100B28F86 /* BoltsSwift.framework */;
430 | productType = "com.apple.product-type.framework";
431 | };
432 | 81CC14F51A9BE0A100B28F86 /* BoltsSwiftTests-macOS */ = {
433 | isa = PBXNativeTarget;
434 | buildConfigurationList = 81CC15021A9BE0A100B28F86 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-macOS" */;
435 | buildPhases = (
436 | 81CC14F21A9BE0A100B28F86 /* Sources */,
437 | 81CC14F31A9BE0A100B28F86 /* Frameworks */,
438 | 81CC14F41A9BE0A100B28F86 /* Resources */,
439 | );
440 | buildRules = (
441 | );
442 | dependencies = (
443 | 81CC14F91A9BE0A100B28F86 /* PBXTargetDependency */,
444 | );
445 | name = "BoltsSwiftTests-macOS";
446 | productName = "Bolts-MacTests";
447 | productReference = 81CC14F61A9BE0A100B28F86 /* BoltsSwiftTests.xctest */;
448 | productType = "com.apple.product-type.bundle.unit-test";
449 | };
450 | 87FEF3651A9085FA00C60678 /* BoltsSwift-iOS */ = {
451 | isa = PBXNativeTarget;
452 | buildConfigurationList = 87FEF37C1A9085FA00C60678 /* Build configuration list for PBXNativeTarget "BoltsSwift-iOS" */;
453 | buildPhases = (
454 | 87FEF3611A9085FA00C60678 /* Sources */,
455 | 87FEF3621A9085FA00C60678 /* Frameworks */,
456 | 87FEF3631A9085FA00C60678 /* Headers */,
457 | 87FEF3641A9085FA00C60678 /* Resources */,
458 | );
459 | buildRules = (
460 | );
461 | dependencies = (
462 | );
463 | name = "BoltsSwift-iOS";
464 | productName = Bolts;
465 | productReference = 87FEF3661A9085FA00C60678 /* BoltsSwift.framework */;
466 | productType = "com.apple.product-type.framework";
467 | };
468 | 87FEF3701A9085FA00C60678 /* BoltsSwiftTests-iOS */ = {
469 | isa = PBXNativeTarget;
470 | buildConfigurationList = 87FEF37F1A9085FA00C60678 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-iOS" */;
471 | buildPhases = (
472 | 87FEF36D1A9085FA00C60678 /* Sources */,
473 | 87FEF36E1A9085FA00C60678 /* Frameworks */,
474 | 87FEF36F1A9085FA00C60678 /* Resources */,
475 | );
476 | buildRules = (
477 | );
478 | dependencies = (
479 | 87FEF3741A9085FA00C60678 /* PBXTargetDependency */,
480 | );
481 | name = "BoltsSwiftTests-iOS";
482 | productName = BoltsTests;
483 | productReference = 87FEF3711A9085FA00C60678 /* BoltsSwiftTests.xctest */;
484 | productType = "com.apple.product-type.bundle.unit-test";
485 | };
486 | /* End PBXNativeTarget section */
487 |
488 | /* Begin PBXProject section */
489 | 87FEF35D1A9085FA00C60678 /* Project object */ = {
490 | isa = PBXProject;
491 | attributes = {
492 | LastSwiftMigration = 0700;
493 | LastSwiftUpdateCheck = 0700;
494 | LastUpgradeCheck = 1100;
495 | ORGANIZATIONNAME = Facebook;
496 | TargetAttributes = {
497 | 065894E61C9A933B000FDDA6 = {
498 | CreatedOnToolsVersion = 7.2.1;
499 | };
500 | 81CC14EB1A9BE0A100B28F86 = {
501 | CreatedOnToolsVersion = 6.3;
502 | };
503 | 81CC14F51A9BE0A100B28F86 = {
504 | CreatedOnToolsVersion = 6.3;
505 | };
506 | 87FEF3651A9085FA00C60678 = {
507 | CreatedOnToolsVersion = 6.3;
508 | LastSwiftMigration = 1100;
509 | };
510 | 87FEF3701A9085FA00C60678 = {
511 | CreatedOnToolsVersion = 6.3;
512 | LastSwiftMigration = 1100;
513 | };
514 | };
515 | };
516 | buildConfigurationList = 87FEF3601A9085FA00C60678 /* Build configuration list for PBXProject "BoltsSwift" */;
517 | compatibilityVersion = "Xcode 3.2";
518 | developmentRegion = English;
519 | hasScannedForEncodings = 0;
520 | knownRegions = (
521 | English,
522 | Base,
523 | );
524 | mainGroup = 87FEF35C1A9085FA00C60678;
525 | productRefGroup = 87FEF3671A9085FA00C60678 /* Products */;
526 | projectDirPath = "";
527 | projectRoot = "";
528 | targets = (
529 | 87FEF3651A9085FA00C60678 /* BoltsSwift-iOS */,
530 | 87FEF3701A9085FA00C60678 /* BoltsSwiftTests-iOS */,
531 | 81CC14EB1A9BE0A100B28F86 /* BoltsSwift-macOS */,
532 | 81CC14F51A9BE0A100B28F86 /* BoltsSwiftTests-macOS */,
533 | 065894F31C9A93B7000FDDA6 /* BoltsSwift-tvOS */,
534 | 0658950E1C9A947B000FDDA6 /* BoltsSwiftTests-tvOS */,
535 | 065894E61C9A933B000FDDA6 /* BoltsSwift-watchOS */,
536 | );
537 | };
538 | /* End PBXProject section */
539 |
540 | /* Begin PBXResourcesBuildPhase section */
541 | 065894E51C9A933B000FDDA6 /* Resources */ = {
542 | isa = PBXResourcesBuildPhase;
543 | buildActionMask = 2147483647;
544 | files = (
545 | );
546 | runOnlyForDeploymentPostprocessing = 0;
547 | };
548 | 065894FB1C9A93B7000FDDA6 /* Resources */ = {
549 | isa = PBXResourcesBuildPhase;
550 | buildActionMask = 2147483647;
551 | files = (
552 | );
553 | runOnlyForDeploymentPostprocessing = 0;
554 | };
555 | 065895171C9A947B000FDDA6 /* Resources */ = {
556 | isa = PBXResourcesBuildPhase;
557 | buildActionMask = 2147483647;
558 | files = (
559 | );
560 | runOnlyForDeploymentPostprocessing = 0;
561 | };
562 | 81CC14EA1A9BE0A100B28F86 /* Resources */ = {
563 | isa = PBXResourcesBuildPhase;
564 | buildActionMask = 2147483647;
565 | files = (
566 | );
567 | runOnlyForDeploymentPostprocessing = 0;
568 | };
569 | 81CC14F41A9BE0A100B28F86 /* Resources */ = {
570 | isa = PBXResourcesBuildPhase;
571 | buildActionMask = 2147483647;
572 | files = (
573 | );
574 | runOnlyForDeploymentPostprocessing = 0;
575 | };
576 | 87FEF3641A9085FA00C60678 /* Resources */ = {
577 | isa = PBXResourcesBuildPhase;
578 | buildActionMask = 2147483647;
579 | files = (
580 | );
581 | runOnlyForDeploymentPostprocessing = 0;
582 | };
583 | 87FEF36F1A9085FA00C60678 /* Resources */ = {
584 | isa = PBXResourcesBuildPhase;
585 | buildActionMask = 2147483647;
586 | files = (
587 | );
588 | runOnlyForDeploymentPostprocessing = 0;
589 | };
590 | /* End PBXResourcesBuildPhase section */
591 |
592 | /* Begin PBXSourcesBuildPhase section */
593 | 065894E21C9A933B000FDDA6 /* Sources */ = {
594 | isa = PBXSourcesBuildPhase;
595 | buildActionMask = 2147483647;
596 | files = (
597 | 065894F21C9A9391000FDDA6 /* Errors.swift in Sources */,
598 | F569C0DA1CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
599 | 065894EF1C9A9391000FDDA6 /* Task.swift in Sources */,
600 | F569C0CF1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
601 | F569C0C41CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
602 | F569C0E41CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
603 | 065894F11C9A9391000FDDA6 /* Executor.swift in Sources */,
604 | 065894F01C9A9391000FDDA6 /* TaskCompletionSource.swift in Sources */,
605 | );
606 | runOnlyForDeploymentPostprocessing = 0;
607 | };
608 | 065894F41C9A93B7000FDDA6 /* Sources */ = {
609 | isa = PBXSourcesBuildPhase;
610 | buildActionMask = 2147483647;
611 | files = (
612 | 065894F51C9A93B7000FDDA6 /* Executor.swift in Sources */,
613 | F569C0D91CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
614 | 065894F61C9A93B7000FDDA6 /* Task.swift in Sources */,
615 | F569C0CE1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
616 | F569C0C31CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
617 | F569C0E31CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
618 | 065894F71C9A93B7000FDDA6 /* Errors.swift in Sources */,
619 | 065894F81C9A93B7000FDDA6 /* TaskCompletionSource.swift in Sources */,
620 | );
621 | runOnlyForDeploymentPostprocessing = 0;
622 | };
623 | 065895111C9A947B000FDDA6 /* Sources */ = {
624 | isa = PBXSourcesBuildPhase;
625 | buildActionMask = 2147483647;
626 | files = (
627 | 065895121C9A947B000FDDA6 /* ExecutorTests.swift in Sources */,
628 | 065895131C9A947B000FDDA6 /* TaskTests.swift in Sources */,
629 | 065895141C9A947B000FDDA6 /* TaskCompletionSourceTests.swift in Sources */,
630 | 810AB3221C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */,
631 | );
632 | runOnlyForDeploymentPostprocessing = 0;
633 | };
634 | 81CC14E71A9BE0A100B28F86 /* Sources */ = {
635 | isa = PBXSourcesBuildPhase;
636 | buildActionMask = 2147483647;
637 | files = (
638 | 81D3006B1C93AF7300E1A1ED /* Executor.swift in Sources */,
639 | F569C0D81CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
640 | 81D3006D1C93AF7300E1A1ED /* Task.swift in Sources */,
641 | F569C0CD1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
642 | F569C0C21CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
643 | F569C0E21CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
644 | 81D300691C93AF7300E1A1ED /* Errors.swift in Sources */,
645 | 81D3006F1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */,
646 | );
647 | runOnlyForDeploymentPostprocessing = 0;
648 | };
649 | 81CC14F21A9BE0A100B28F86 /* Sources */ = {
650 | isa = PBXSourcesBuildPhase;
651 | buildActionMask = 2147483647;
652 | files = (
653 | 81D3007A1C93AF9F00E1A1ED /* ExecutorTests.swift in Sources */,
654 | 81D300801C93AF9F00E1A1ED /* TaskTests.swift in Sources */,
655 | 81D3007E1C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift in Sources */,
656 | 810AB3211C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */,
657 | );
658 | runOnlyForDeploymentPostprocessing = 0;
659 | };
660 | 87FEF3611A9085FA00C60678 /* Sources */ = {
661 | isa = PBXSourcesBuildPhase;
662 | buildActionMask = 2147483647;
663 | files = (
664 | 81D3006A1C93AF7300E1A1ED /* Executor.swift in Sources */,
665 | F569C0D71CFF6B18000749B6 /* Task+WhenAll.swift in Sources */,
666 | 81D3006C1C93AF7300E1A1ED /* Task.swift in Sources */,
667 | F569C0CC1CFF6AEE000749B6 /* Task+Delay.swift in Sources */,
668 | F569C0C11CFF6A07000749B6 /* Task+ContinueWith.swift in Sources */,
669 | F569C0E11CFF6B1F000749B6 /* Task+WhenAny.swift in Sources */,
670 | 81D300681C93AF7300E1A1ED /* Errors.swift in Sources */,
671 | 81D3006E1C93AF7300E1A1ED /* TaskCompletionSource.swift in Sources */,
672 | );
673 | runOnlyForDeploymentPostprocessing = 0;
674 | };
675 | 87FEF36D1A9085FA00C60678 /* Sources */ = {
676 | isa = PBXSourcesBuildPhase;
677 | buildActionMask = 2147483647;
678 | files = (
679 | 81D300791C93AF9F00E1A1ED /* ExecutorTests.swift in Sources */,
680 | 81D3007F1C93AF9F00E1A1ED /* TaskTests.swift in Sources */,
681 | 81D3007D1C93AF9F00E1A1ED /* TaskCompletionSourceTests.swift in Sources */,
682 | 810AB3201C9B1AC3005B6184 /* XCTestCase+TestName.swift in Sources */,
683 | );
684 | runOnlyForDeploymentPostprocessing = 0;
685 | };
686 | /* End PBXSourcesBuildPhase section */
687 |
688 | /* Begin PBXTargetDependency section */
689 | 0658951E1C9A948E000FDDA6 /* PBXTargetDependency */ = {
690 | isa = PBXTargetDependency;
691 | target = 065894F31C9A93B7000FDDA6 /* BoltsSwift-tvOS */;
692 | targetProxy = 0658951D1C9A948E000FDDA6 /* PBXContainerItemProxy */;
693 | };
694 | 81CC14F91A9BE0A100B28F86 /* PBXTargetDependency */ = {
695 | isa = PBXTargetDependency;
696 | target = 81CC14EB1A9BE0A100B28F86 /* BoltsSwift-macOS */;
697 | targetProxy = 81CC14F81A9BE0A100B28F86 /* PBXContainerItemProxy */;
698 | };
699 | 87FEF3741A9085FA00C60678 /* PBXTargetDependency */ = {
700 | isa = PBXTargetDependency;
701 | target = 87FEF3651A9085FA00C60678 /* BoltsSwift-iOS */;
702 | targetProxy = 87FEF3731A9085FA00C60678 /* PBXContainerItemProxy */;
703 | };
704 | /* End PBXTargetDependency section */
705 |
706 | /* Begin XCBuildConfiguration section */
707 | 065894EC1C9A933B000FDDA6 /* Debug */ = {
708 | isa = XCBuildConfiguration;
709 | baseConfigurationReference = 812DB52A1D3597BF00552C9F /* BoltsSwift-watchOS.xcconfig */;
710 | buildSettings = {
711 | };
712 | name = Debug;
713 | };
714 | 065894ED1C9A933B000FDDA6 /* Release */ = {
715 | isa = XCBuildConfiguration;
716 | baseConfigurationReference = 812DB52A1D3597BF00552C9F /* BoltsSwift-watchOS.xcconfig */;
717 | buildSettings = {
718 | };
719 | name = Release;
720 | };
721 | 065894FD1C9A93B7000FDDA6 /* Debug */ = {
722 | isa = XCBuildConfiguration;
723 | baseConfigurationReference = 812DB5291D3597BF00552C9F /* BoltsSwift-tvOS.xcconfig */;
724 | buildSettings = {
725 | };
726 | name = Debug;
727 | };
728 | 065894FE1C9A93B7000FDDA6 /* Release */ = {
729 | isa = XCBuildConfiguration;
730 | baseConfigurationReference = 812DB5291D3597BF00552C9F /* BoltsSwift-tvOS.xcconfig */;
731 | buildSettings = {
732 | };
733 | name = Release;
734 | };
735 | 065895191C9A947B000FDDA6 /* Debug */ = {
736 | isa = XCBuildConfiguration;
737 | baseConfigurationReference = 812DB52D1D3597BF00552C9F /* BoltsSwiftTests-tvOS.xcconfig */;
738 | buildSettings = {
739 | };
740 | name = Debug;
741 | };
742 | 0658951A1C9A947B000FDDA6 /* Release */ = {
743 | isa = XCBuildConfiguration;
744 | baseConfigurationReference = 812DB52D1D3597BF00552C9F /* BoltsSwiftTests-tvOS.xcconfig */;
745 | buildSettings = {
746 | };
747 | name = Release;
748 | };
749 | 81CC15001A9BE0A100B28F86 /* Debug */ = {
750 | isa = XCBuildConfiguration;
751 | baseConfigurationReference = 812DB5281D3597BF00552C9F /* BoltsSwift-macOS.xcconfig */;
752 | buildSettings = {
753 | };
754 | name = Debug;
755 | };
756 | 81CC15011A9BE0A100B28F86 /* Release */ = {
757 | isa = XCBuildConfiguration;
758 | baseConfigurationReference = 812DB5281D3597BF00552C9F /* BoltsSwift-macOS.xcconfig */;
759 | buildSettings = {
760 | };
761 | name = Release;
762 | };
763 | 81CC15031A9BE0A100B28F86 /* Debug */ = {
764 | isa = XCBuildConfiguration;
765 | baseConfigurationReference = 812DB52C1D3597BF00552C9F /* BoltsSwiftTests-macOS.xcconfig */;
766 | buildSettings = {
767 | };
768 | name = Debug;
769 | };
770 | 81CC15041A9BE0A100B28F86 /* Release */ = {
771 | isa = XCBuildConfiguration;
772 | baseConfigurationReference = 812DB52C1D3597BF00552C9F /* BoltsSwiftTests-macOS.xcconfig */;
773 | buildSettings = {
774 | };
775 | name = Release;
776 | };
777 | 87FEF37A1A9085FA00C60678 /* Debug */ = {
778 | isa = XCBuildConfiguration;
779 | baseConfigurationReference = 812DB53B1D3597BF00552C9F /* Debug.xcconfig */;
780 | buildSettings = {
781 | };
782 | name = Debug;
783 | };
784 | 87FEF37B1A9085FA00C60678 /* Release */ = {
785 | isa = XCBuildConfiguration;
786 | baseConfigurationReference = 812DB53C1D3597BF00552C9F /* Release.xcconfig */;
787 | buildSettings = {
788 | };
789 | name = Release;
790 | };
791 | 87FEF37D1A9085FA00C60678 /* Debug */ = {
792 | isa = XCBuildConfiguration;
793 | baseConfigurationReference = 812DB5271D3597BF00552C9F /* BoltsSwift-iOS.xcconfig */;
794 | buildSettings = {
795 | };
796 | name = Debug;
797 | };
798 | 87FEF37E1A9085FA00C60678 /* Release */ = {
799 | isa = XCBuildConfiguration;
800 | baseConfigurationReference = 812DB5271D3597BF00552C9F /* BoltsSwift-iOS.xcconfig */;
801 | buildSettings = {
802 | };
803 | name = Release;
804 | };
805 | 87FEF3801A9085FA00C60678 /* Debug */ = {
806 | isa = XCBuildConfiguration;
807 | baseConfigurationReference = 812DB52B1D3597BF00552C9F /* BoltsSwiftTests-iOS.xcconfig */;
808 | buildSettings = {
809 | };
810 | name = Debug;
811 | };
812 | 87FEF3811A9085FA00C60678 /* Release */ = {
813 | isa = XCBuildConfiguration;
814 | baseConfigurationReference = 812DB52B1D3597BF00552C9F /* BoltsSwiftTests-iOS.xcconfig */;
815 | buildSettings = {
816 | };
817 | name = Release;
818 | };
819 | /* End XCBuildConfiguration section */
820 |
821 | /* Begin XCConfigurationList section */
822 | 065894EE1C9A933B000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwift-watchOS" */ = {
823 | isa = XCConfigurationList;
824 | buildConfigurations = (
825 | 065894EC1C9A933B000FDDA6 /* Debug */,
826 | 065894ED1C9A933B000FDDA6 /* Release */,
827 | );
828 | defaultConfigurationIsVisible = 0;
829 | defaultConfigurationName = Release;
830 | };
831 | 065894FC1C9A93B7000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwift-tvOS" */ = {
832 | isa = XCConfigurationList;
833 | buildConfigurations = (
834 | 065894FD1C9A93B7000FDDA6 /* Debug */,
835 | 065894FE1C9A93B7000FDDA6 /* Release */,
836 | );
837 | defaultConfigurationIsVisible = 0;
838 | defaultConfigurationName = Release;
839 | };
840 | 065895181C9A947B000FDDA6 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-tvOS" */ = {
841 | isa = XCConfigurationList;
842 | buildConfigurations = (
843 | 065895191C9A947B000FDDA6 /* Debug */,
844 | 0658951A1C9A947B000FDDA6 /* Release */,
845 | );
846 | defaultConfigurationIsVisible = 0;
847 | defaultConfigurationName = Release;
848 | };
849 | 81CC14FF1A9BE0A100B28F86 /* Build configuration list for PBXNativeTarget "BoltsSwift-macOS" */ = {
850 | isa = XCConfigurationList;
851 | buildConfigurations = (
852 | 81CC15001A9BE0A100B28F86 /* Debug */,
853 | 81CC15011A9BE0A100B28F86 /* Release */,
854 | );
855 | defaultConfigurationIsVisible = 0;
856 | defaultConfigurationName = Release;
857 | };
858 | 81CC15021A9BE0A100B28F86 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-macOS" */ = {
859 | isa = XCConfigurationList;
860 | buildConfigurations = (
861 | 81CC15031A9BE0A100B28F86 /* Debug */,
862 | 81CC15041A9BE0A100B28F86 /* Release */,
863 | );
864 | defaultConfigurationIsVisible = 0;
865 | defaultConfigurationName = Release;
866 | };
867 | 87FEF3601A9085FA00C60678 /* Build configuration list for PBXProject "BoltsSwift" */ = {
868 | isa = XCConfigurationList;
869 | buildConfigurations = (
870 | 87FEF37A1A9085FA00C60678 /* Debug */,
871 | 87FEF37B1A9085FA00C60678 /* Release */,
872 | );
873 | defaultConfigurationIsVisible = 0;
874 | defaultConfigurationName = Release;
875 | };
876 | 87FEF37C1A9085FA00C60678 /* Build configuration list for PBXNativeTarget "BoltsSwift-iOS" */ = {
877 | isa = XCConfigurationList;
878 | buildConfigurations = (
879 | 87FEF37D1A9085FA00C60678 /* Debug */,
880 | 87FEF37E1A9085FA00C60678 /* Release */,
881 | );
882 | defaultConfigurationIsVisible = 0;
883 | defaultConfigurationName = Release;
884 | };
885 | 87FEF37F1A9085FA00C60678 /* Build configuration list for PBXNativeTarget "BoltsSwiftTests-iOS" */ = {
886 | isa = XCConfigurationList;
887 | buildConfigurations = (
888 | 87FEF3801A9085FA00C60678 /* Debug */,
889 | 87FEF3811A9085FA00C60678 /* Release */,
890 | );
891 | defaultConfigurationIsVisible = 0;
892 | defaultConfigurationName = Release;
893 | };
894 | /* End XCConfigurationList section */
895 | };
896 | rootObject = 87FEF35D1A9085FA00C60678 /* Project object */;
897 | }
898 |
--------------------------------------------------------------------------------