├── .gitignore ├── Synchronized.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── Synchronized.xccheckout ├── xcshareddata │ └── xcschemes │ │ ├── Synchronized.xcscheme │ │ └── SynchronizedTests.xcscheme └── project.pbxproj ├── .github └── workflows │ └── tests.yml ├── SynchronizedTests ├── Info.plist └── SynchronizedTests.swift ├── Synchronized ├── Info.plist ├── ObjCSynchronized.m ├── ObjCSynchronized.h ├── Synchronized.h └── Synchronized.swift ├── Synchronized.podspec ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | xcuserdata/ 6 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: push 4 | 5 | jobs: 6 | tests: 7 | name: Run iOS tests 8 | runs-on: macos-latest 9 | 10 | steps: 11 | - name: Check out code 12 | uses: actions/checkout@v2 13 | - name: Run unit tests 14 | run: > 15 | xcodebuild 16 | -project Synchronized.xcodeproj 17 | -scheme SynchronizedTests 18 | -sdk iphonesimulator 19 | -destination "platform=iOS Simulator,name=iPhone 12" 20 | -quiet 21 | ONLY_ACTIVE_ARCH=NO 22 | test 23 | -------------------------------------------------------------------------------- /SynchronizedTests/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 | -------------------------------------------------------------------------------- /Synchronized/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 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Synchronized.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "Synchronized" 3 | s.version = "4.0.0" 4 | s.summary = "Exposes Objective-C's @synchronized directive to Swift" 5 | s.description = <<-DESC 6 | A simple way to use Objective-C's `@synchronized` 7 | directive from Swift. 8 | 9 | As with `@synchronized`, Synchronized releases locks when 10 | Objective-C exceptions are thrown. 11 | DESC 12 | s.homepage = "https://github.com/ide/Synchronized" 13 | s.license = "MIT" 14 | s.author = "James Ide" 15 | s.source = { :git => "https://github.com/ide/Synchronized.git", :tag => s.version.to_s } 16 | s.swift_version = '5.4' 17 | s.platform = :ios, '12.0' 18 | s.requires_arc = true 19 | s.source_files = [ 20 | 'Synchronized/Synchronized.swift', 21 | 'Synchronized/ObjCSynchronized.{h,m}' 22 | ] 23 | s.public_header_files = [] 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-present James Ide 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Synchronized/ObjCSynchronized.m: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014-present James Ide 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "ObjCSynchronized.h" 24 | 25 | void objc_synchronized(id object, void (^closure)(void)) 26 | { 27 | @synchronized(object) { 28 | closure(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Synchronized/ObjCSynchronized.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014-present James Ide 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | @import Foundation; 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | void objc_synchronized(id object, __attribute__((noescape)) void (^closure)(void)); 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /Synchronized/Synchronized.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014-present James Ide 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | @import Foundation; 24 | 25 | //! Project version number for Synchronized. 26 | FOUNDATION_EXPORT double SynchronizedVersionNumber; 27 | 28 | //! Project version string for Synchronized. 29 | FOUNDATION_EXPORT const unsigned char SynchronizedVersionString[]; 30 | 31 | #import "ObjCSynchronized.h" 32 | -------------------------------------------------------------------------------- /Synchronized/Synchronized.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014-present James Ide 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | public func synchronized(_ object: AnyObject, closure: () -> T) -> T { 24 | var result: T? = nil 25 | objc_synchronized(object) { 26 | result = closure() 27 | } 28 | return result! 29 | } 30 | 31 | public func synchronized(_ object: AnyObject, closure: () -> Void) { 32 | objc_synchronized(object, closure) 33 | } 34 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/project.xcworkspace/xcshareddata/Synchronized.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 69A3A745-40D8-4D05-979D-94EAA8B0107B 9 | IDESourceControlProjectName 10 | Synchronized 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C4B28623BC71688399A46D5D7A7AF1E003D96E4A 14 | github.com:ide/Synchronized.git 15 | 16 | IDESourceControlProjectPath 17 | Synchronized.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C4B28623BC71688399A46D5D7A7AF1E003D96E4A 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:ide/Synchronized.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C4B28623BC71688399A46D5D7A7AF1E003D96E4A 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C4B28623BC71688399A46D5D7A7AF1E003D96E4A 36 | IDESourceControlWCCName 37 | Synchronized 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Synchronized ![Tests](https://github.com/ide/synchronized/actions/workflows/tests.yml/badge.svg) 2 | ============ 3 | 4 | [![Version](https://img.shields.io/cocoapods/v/Synchronized.svg?style=flat)](http://cocoadocs.org/docsets/Synchronized) 5 | [![License](https://img.shields.io/cocoapods/l/Synchronized.svg?style=flat)](http://cocoadocs.org/docsets/Synchronized) 6 | [![Platform](https://img.shields.io/cocoapods/p/Synchronized.svg?style=flat)](http://cocoadocs.org/docsets/Synchronized) 7 | 8 | Exposes Objective-C's @synchronized directive to Swift. Like the Objective-C directive, Synchronized acquires a mutex lock, runs some code, and releases the lock when the code completes or throws an exception. 9 | 10 | Linking the Framework 11 | --- 12 | 13 | Synchronized is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile: 14 | 15 | pod "Synchronized", "~> 4.0" 16 | 17 | You can also use [Carthage](https://github.com/Carthage/Carthage) to fetch it from GitHub: 18 | 19 | github "ide/Synchronized" ~> 4.0 20 | 21 | Once the framework is linked this Swift code should compile: 22 | ```swift 23 | import Synchronized 24 | 25 | let x = synchronized(NSObject()) { 0 } 26 | ``` 27 | 28 | Public API 29 | --- 30 | 31 | ```swift 32 | public func synchronized(object: AnyObject, closure: () -> Void) 33 | ``` 34 | 35 | **Usage:** 36 | ```swift 37 | synchronized(mutexObject) { 38 | // Code to run in your critical section 39 | } 40 | ``` 41 | 42 | --- 43 | 44 | ```swift 45 | public func synchronized(object: AnyObject, closure: () -> T) -> T 46 | ``` 47 | 48 | **Usage:** 49 | ```swift 50 | let value = synchronized(threadUnsafeDictionary) { 51 | threadUnsafeDictionary[key] 52 | } 53 | ``` 54 | 55 | Differences from `@synchronized` 56 | --- 57 | 58 | Objective-C's `@synchronized` is a language-level directive and does not introduce a new function scope. This means that `return` statements cause the program to return from the surrounding function that contains the `@synchronized` directive. 59 | 60 | ```objc 61 | - (void)returnDifferenceExample 62 | { 63 | @synchronized { 64 | return; 65 | } 66 | NSLog(@"This line of code does not run."); 67 | } 68 | ``` 69 | 70 | In contrast, Synchronized uses closures which do introduce a function scope. Returning from a closure passed to `synchronized` exits only the closure, not the surrounding function. 71 | 72 | ```swift 73 | func returnDifferenceExample() { 74 | synchronized { 75 | return 76 | } 77 | println("This line of code does run.") 78 | } 79 | ``` 80 | 81 | Synchronized's closures are annotated with the `@noclosure` attribute, which removes the need to access instance variables with `self.`, so it is similar to Objective-C's `@synchronized` directive in this regard. 82 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/xcshareddata/xcschemes/Synchronized.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 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/xcshareddata/xcschemes/SynchronizedTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /SynchronizedTests/SynchronizedTests.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014-present James Ide 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | import Synchronized 24 | import XCTest 25 | 26 | class SynchronizedTests: XCTestCase { 27 | 28 | // MARK: - Return values 29 | 30 | func testVoidReturnValue() { 31 | // Ensure that passing in a closure without a return value compiles 32 | let mutex = NSObject() 33 | synchronized(mutex) {} 34 | } 35 | 36 | func testNSObjectReturnValue() { 37 | let mutex = NSObject() 38 | let value = NSObject() 39 | let returnedValue = synchronized(mutex) { value } 40 | XCTAssertEqual(value, returnedValue, "Returned value should be the expected NSObject") 41 | } 42 | 43 | func testSwiftObjectReturnValue() { 44 | let mutex = NSObject() 45 | class SwiftObject {} 46 | let value = SwiftObject() 47 | let returnedValue = synchronized(mutex) { value } 48 | XCTAssertEqual(ObjectIdentifier(value), ObjectIdentifier(returnedValue), 49 | "Returned value should be the expected Swift object") 50 | } 51 | 52 | func testNilReturnValue() { 53 | let mutex = NSObject() 54 | let returnedValue: AnyObject? = synchronized(mutex) { nil } 55 | XCTAssertNil(returnedValue, "Returned value should be nil") 56 | } 57 | 58 | // MARK: - Mutex types 59 | 60 | func testSwiftObjectMutex() { 61 | class SwiftObject {} 62 | let mutex = SwiftObject() 63 | synchronized(mutex) {} 64 | } 65 | 66 | // MARK: - Concurrency 67 | 68 | func testMutualExclusion() { 69 | let mutexA = NSObject() 70 | let mutexB = NSObject() 71 | 72 | let expectationA1 = expectation(description: "Finished operation 1 with mutex A") 73 | let expectationA2 = expectation(description: "Finished operation 2 with mutex A") 74 | let expectationB1 = expectation(description: "Finished operation 1 with mutex B") 75 | 76 | let concurrentQueue = DispatchQueue(label: "SynchronizedTests.testMutualExclusion", attributes: DispatchQueue.Attributes.concurrent) 77 | 78 | concurrentQueue.async { 79 | synchronized(mutexA) { 80 | var operationA1DidFinish = false 81 | var operationA2DidFinish = false 82 | var operationB1DidFinish = false 83 | 84 | // Dispatch a subtask that acquires the same mutex 85 | let a2ActiveCondition = NSCondition() 86 | a2ActiveCondition.lock() 87 | 88 | concurrentQueue.async { 89 | a2ActiveCondition.lock() 90 | a2ActiveCondition.signal() 91 | a2ActiveCondition.unlock() 92 | 93 | synchronized(mutexA) { 94 | XCTAssert(operationA1DidFinish, "Operation A1 did not finish before A2") 95 | operationA2DidFinish = true 96 | expectationA2.fulfill() 97 | } 98 | } 99 | 100 | // Wait for operation A2 to begin 101 | a2ActiveCondition.wait() 102 | a2ActiveCondition.unlock() 103 | 104 | // Dispatch a subtask that acquires a different mutex and should run concurrently 105 | let b1ActiveCondition = NSCondition() 106 | b1ActiveCondition.lock() 107 | 108 | concurrentQueue.async { 109 | b1ActiveCondition.lock() 110 | b1ActiveCondition.signal() 111 | b1ActiveCondition.unlock() 112 | synchronized(mutexB) { 113 | operationB1DidFinish = true 114 | expectationB1.fulfill() 115 | } 116 | } 117 | 118 | // Wait for operation B1 to begin 119 | b1ActiveCondition.wait() 120 | b1ActiveCondition.unlock() 121 | 122 | Thread.sleep(forTimeInterval: 0.2) 123 | 124 | XCTAssert(!operationA2DidFinish, "Operation A2 did not wait for A1") 125 | XCTAssert(operationB1DidFinish, "Operation B1 did not finish before A1") 126 | 127 | operationA1DidFinish = true 128 | expectationA1.fulfill() 129 | } 130 | } 131 | 132 | waitForExpectations(timeout: 1) { error in 133 | if let error = error { 134 | XCTFail(error.localizedDescription) 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Synchronized.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 78C901E419C8BFDA0042C514 /* Synchronized.h in Headers */ = {isa = PBXBuildFile; fileRef = 78C901E319C8BFDA0042C514 /* Synchronized.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 78C901EE19C8BFDA0042C514 /* SynchronizedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78C901ED19C8BFDA0042C514 /* SynchronizedTests.swift */; }; 12 | 78C901F819C8C05F0042C514 /* Synchronized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78C901F719C8C05F0042C514 /* Synchronized.swift */; }; 13 | 78C901FA19C8C0E40042C514 /* ObjCSynchronized.m in Sources */ = {isa = PBXBuildFile; fileRef = 78C901F919C8C0E40042C514 /* ObjCSynchronized.m */; }; 14 | 78C901FE19C8C1FD0042C514 /* ObjCSynchronized.h in Headers */ = {isa = PBXBuildFile; fileRef = 78C901FD19C8C1FD0042C514 /* ObjCSynchronized.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXContainerItemProxy section */ 18 | 78C901FF19C8C7090042C514 /* PBXContainerItemProxy */ = { 19 | isa = PBXContainerItemProxy; 20 | containerPortal = 78C901D519C8BFDA0042C514 /* Project object */; 21 | proxyType = 1; 22 | remoteGlobalIDString = 78C901DD19C8BFDA0042C514; 23 | remoteInfo = Synchronized; 24 | }; 25 | /* End PBXContainerItemProxy section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 78C901DE19C8BFDA0042C514 /* Synchronized.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Synchronized.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 78C901E219C8BFDA0042C514 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 78C901E319C8BFDA0042C514 /* Synchronized.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Synchronized.h; sourceTree = ""; }; 31 | 78C901E919C8BFDA0042C514 /* SynchronizedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SynchronizedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 78C901EC19C8BFDA0042C514 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 78C901ED19C8BFDA0042C514 /* SynchronizedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynchronizedTests.swift; sourceTree = ""; }; 34 | 78C901F719C8C05F0042C514 /* Synchronized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Synchronized.swift; sourceTree = ""; }; 35 | 78C901F919C8C0E40042C514 /* ObjCSynchronized.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCSynchronized.m; sourceTree = ""; }; 36 | 78C901FD19C8C1FD0042C514 /* ObjCSynchronized.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjCSynchronized.h; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 78C901DA19C8BFDA0042C514 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | 78C901E619C8BFDA0042C514 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 78C901D419C8BFDA0042C514 = { 58 | isa = PBXGroup; 59 | children = ( 60 | 78C901DF19C8BFDA0042C514 /* Products */, 61 | 78C901E019C8BFDA0042C514 /* Synchronized */, 62 | 78C901EA19C8BFDA0042C514 /* SynchronizedTests */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 78C901DF19C8BFDA0042C514 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 78C901DE19C8BFDA0042C514 /* Synchronized.framework */, 70 | 78C901E919C8BFDA0042C514 /* SynchronizedTests.xctest */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 78C901E019C8BFDA0042C514 /* Synchronized */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 78C901E119C8BFDA0042C514 /* Supporting Files */, 79 | 78C901FD19C8C1FD0042C514 /* ObjCSynchronized.h */, 80 | 78C901F919C8C0E40042C514 /* ObjCSynchronized.m */, 81 | 78C901F719C8C05F0042C514 /* Synchronized.swift */, 82 | 78C901E319C8BFDA0042C514 /* Synchronized.h */, 83 | ); 84 | path = Synchronized; 85 | sourceTree = ""; 86 | }; 87 | 78C901E119C8BFDA0042C514 /* Supporting Files */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 78C901E219C8BFDA0042C514 /* Info.plist */, 91 | ); 92 | name = "Supporting Files"; 93 | sourceTree = ""; 94 | }; 95 | 78C901EA19C8BFDA0042C514 /* SynchronizedTests */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 78C901EB19C8BFDA0042C514 /* Supporting Files */, 99 | 78C901ED19C8BFDA0042C514 /* SynchronizedTests.swift */, 100 | ); 101 | path = SynchronizedTests; 102 | sourceTree = ""; 103 | }; 104 | 78C901EB19C8BFDA0042C514 /* Supporting Files */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 78C901EC19C8BFDA0042C514 /* Info.plist */, 108 | ); 109 | name = "Supporting Files"; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXHeadersBuildPhase section */ 115 | 78C901DB19C8BFDA0042C514 /* Headers */ = { 116 | isa = PBXHeadersBuildPhase; 117 | buildActionMask = 2147483647; 118 | files = ( 119 | 78C901FE19C8C1FD0042C514 /* ObjCSynchronized.h in Headers */, 120 | 78C901E419C8BFDA0042C514 /* Synchronized.h in Headers */, 121 | ); 122 | runOnlyForDeploymentPostprocessing = 0; 123 | }; 124 | /* End PBXHeadersBuildPhase section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 78C901DD19C8BFDA0042C514 /* Synchronized */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 78C901F119C8BFDA0042C514 /* Build configuration list for PBXNativeTarget "Synchronized" */; 130 | buildPhases = ( 131 | 78C901D919C8BFDA0042C514 /* Sources */, 132 | 78C901DA19C8BFDA0042C514 /* Frameworks */, 133 | 78C901DB19C8BFDA0042C514 /* Headers */, 134 | 78C901DC19C8BFDA0042C514 /* Resources */, 135 | ); 136 | buildRules = ( 137 | ); 138 | dependencies = ( 139 | ); 140 | name = Synchronized; 141 | productName = Synchronized; 142 | productReference = 78C901DE19C8BFDA0042C514 /* Synchronized.framework */; 143 | productType = "com.apple.product-type.framework"; 144 | }; 145 | 78C901E819C8BFDA0042C514 /* SynchronizedTests */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = 78C901F419C8BFDA0042C514 /* Build configuration list for PBXNativeTarget "SynchronizedTests" */; 148 | buildPhases = ( 149 | 78C901E519C8BFDA0042C514 /* Sources */, 150 | 78C901E619C8BFDA0042C514 /* Frameworks */, 151 | 78C901E719C8BFDA0042C514 /* Resources */, 152 | ); 153 | buildRules = ( 154 | ); 155 | dependencies = ( 156 | 78C9020019C8C7090042C514 /* PBXTargetDependency */, 157 | ); 158 | name = SynchronizedTests; 159 | productName = SynchronizedTests; 160 | productReference = 78C901E919C8BFDA0042C514 /* SynchronizedTests.xctest */; 161 | productType = "com.apple.product-type.bundle.unit-test"; 162 | }; 163 | /* End PBXNativeTarget section */ 164 | 165 | /* Begin PBXProject section */ 166 | 78C901D519C8BFDA0042C514 /* Project object */ = { 167 | isa = PBXProject; 168 | attributes = { 169 | LastSwiftUpdateCheck = 0700; 170 | LastUpgradeCheck = 1240; 171 | ORGANIZATIONNAME = ide; 172 | TargetAttributes = { 173 | 78C901DD19C8BFDA0042C514 = { 174 | CreatedOnToolsVersion = 6.0; 175 | LastSwiftMigration = 1100; 176 | }; 177 | 78C901E819C8BFDA0042C514 = { 178 | CreatedOnToolsVersion = 6.0; 179 | LastSwiftMigration = 1100; 180 | }; 181 | }; 182 | }; 183 | buildConfigurationList = 78C901D819C8BFDA0042C514 /* Build configuration list for PBXProject "Synchronized" */; 184 | compatibilityVersion = "Xcode 3.2"; 185 | developmentRegion = en; 186 | hasScannedForEncodings = 0; 187 | knownRegions = ( 188 | en, 189 | Base, 190 | ); 191 | mainGroup = 78C901D419C8BFDA0042C514; 192 | productRefGroup = 78C901DF19C8BFDA0042C514 /* Products */; 193 | projectDirPath = ""; 194 | projectRoot = ""; 195 | targets = ( 196 | 78C901DD19C8BFDA0042C514 /* Synchronized */, 197 | 78C901E819C8BFDA0042C514 /* SynchronizedTests */, 198 | ); 199 | }; 200 | /* End PBXProject section */ 201 | 202 | /* Begin PBXResourcesBuildPhase section */ 203 | 78C901DC19C8BFDA0042C514 /* Resources */ = { 204 | isa = PBXResourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | 78C901E719C8BFDA0042C514 /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXResourcesBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 78C901D919C8BFDA0042C514 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 78C901FA19C8C0E40042C514 /* ObjCSynchronized.m in Sources */, 225 | 78C901F819C8C05F0042C514 /* Synchronized.swift in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | 78C901E519C8BFDA0042C514 /* Sources */ = { 230 | isa = PBXSourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 78C901EE19C8BFDA0042C514 /* SynchronizedTests.swift in Sources */, 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXSourcesBuildPhase section */ 238 | 239 | /* Begin PBXTargetDependency section */ 240 | 78C9020019C8C7090042C514 /* PBXTargetDependency */ = { 241 | isa = PBXTargetDependency; 242 | target = 78C901DD19C8BFDA0042C514 /* Synchronized */; 243 | targetProxy = 78C901FF19C8C7090042C514 /* PBXContainerItemProxy */; 244 | }; 245 | /* End PBXTargetDependency section */ 246 | 247 | /* Begin XCBuildConfiguration section */ 248 | 78C901EF19C8BFDA0042C514 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_COMMA = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 262 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INFINITE_RECURSION = YES; 266 | CLANG_WARN_INT_CONVERSION = YES; 267 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 269 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 270 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 271 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 273 | CLANG_WARN_STRICT_PROTOTYPES = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | COPY_PHASE_STRIP = NO; 278 | CURRENT_PROJECT_VERSION = 1; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | ENABLE_TESTABILITY = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu99; 282 | GCC_DYNAMIC_NO_PIC = NO; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_OPTIMIZATION_LEVEL = 0; 285 | GCC_PREPROCESSOR_DEFINITIONS = ( 286 | "DEBUG=1", 287 | "$(inherited)", 288 | ); 289 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 297 | MTL_ENABLE_DEBUG_INFO = YES; 298 | ONLY_ACTIVE_ARCH = YES; 299 | SDKROOT = iphoneos; 300 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 301 | TARGETED_DEVICE_FAMILY = "1,2"; 302 | VERSIONING_SYSTEM = "apple-generic"; 303 | VERSION_INFO_PREFIX = ""; 304 | }; 305 | name = Debug; 306 | }; 307 | 78C901F019C8BFDA0042C514 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_COMMA = YES; 319 | CLANG_WARN_CONSTANT_CONVERSION = YES; 320 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 331 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 332 | CLANG_WARN_STRICT_PROTOTYPES = YES; 333 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 334 | CLANG_WARN_UNREACHABLE_CODE = YES; 335 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 336 | COPY_PHASE_STRIP = YES; 337 | CURRENT_PROJECT_VERSION = 1; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | SDKROOT = iphoneos; 351 | TARGETED_DEVICE_FAMILY = "1,2"; 352 | VALIDATE_PRODUCT = YES; 353 | VERSIONING_SYSTEM = "apple-generic"; 354 | VERSION_INFO_PREFIX = ""; 355 | }; 356 | name = Release; 357 | }; 358 | 78C901F219C8BFDA0042C514 /* Debug */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | CLANG_ENABLE_MODULES = YES; 362 | DEFINES_MODULE = YES; 363 | DYLIB_COMPATIBILITY_VERSION = 1; 364 | DYLIB_CURRENT_VERSION = 1; 365 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 366 | INFOPLIST_FILE = Synchronized/Info.plist; 367 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 369 | PRODUCT_BUNDLE_IDENTIFIER = "swift.ide.$(PRODUCT_NAME:rfc1034identifier)"; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SKIP_INSTALL = YES; 372 | SWIFT_VERSION = 5.0; 373 | }; 374 | name = Debug; 375 | }; 376 | 78C901F319C8BFDA0042C514 /* Release */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | CLANG_ENABLE_MODULES = YES; 380 | DEFINES_MODULE = YES; 381 | DYLIB_COMPATIBILITY_VERSION = 1; 382 | DYLIB_CURRENT_VERSION = 1; 383 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 384 | INFOPLIST_FILE = Synchronized/Info.plist; 385 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 386 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 387 | PRODUCT_BUNDLE_IDENTIFIER = "swift.ide.$(PRODUCT_NAME:rfc1034identifier)"; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | SKIP_INSTALL = YES; 390 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 391 | SWIFT_VERSION = 5.0; 392 | }; 393 | name = Release; 394 | }; 395 | 78C901F519C8BFDA0042C514 /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | GCC_PREPROCESSOR_DEFINITIONS = ( 399 | "DEBUG=1", 400 | "$(inherited)", 401 | ); 402 | INFOPLIST_FILE = SynchronizedTests/Info.plist; 403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 404 | PRODUCT_BUNDLE_IDENTIFIER = "swift.ide.$(PRODUCT_NAME:rfc1034identifier)"; 405 | PRODUCT_NAME = "$(TARGET_NAME)"; 406 | SWIFT_VERSION = 5.0; 407 | }; 408 | name = Debug; 409 | }; 410 | 78C901F619C8BFDA0042C514 /* Release */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | INFOPLIST_FILE = SynchronizedTests/Info.plist; 414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 415 | PRODUCT_BUNDLE_IDENTIFIER = "swift.ide.$(PRODUCT_NAME:rfc1034identifier)"; 416 | PRODUCT_NAME = "$(TARGET_NAME)"; 417 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 418 | SWIFT_VERSION = 5.0; 419 | }; 420 | name = Release; 421 | }; 422 | /* End XCBuildConfiguration section */ 423 | 424 | /* Begin XCConfigurationList section */ 425 | 78C901D819C8BFDA0042C514 /* Build configuration list for PBXProject "Synchronized" */ = { 426 | isa = XCConfigurationList; 427 | buildConfigurations = ( 428 | 78C901EF19C8BFDA0042C514 /* Debug */, 429 | 78C901F019C8BFDA0042C514 /* Release */, 430 | ); 431 | defaultConfigurationIsVisible = 0; 432 | defaultConfigurationName = Release; 433 | }; 434 | 78C901F119C8BFDA0042C514 /* Build configuration list for PBXNativeTarget "Synchronized" */ = { 435 | isa = XCConfigurationList; 436 | buildConfigurations = ( 437 | 78C901F219C8BFDA0042C514 /* Debug */, 438 | 78C901F319C8BFDA0042C514 /* Release */, 439 | ); 440 | defaultConfigurationIsVisible = 0; 441 | defaultConfigurationName = Release; 442 | }; 443 | 78C901F419C8BFDA0042C514 /* Build configuration list for PBXNativeTarget "SynchronizedTests" */ = { 444 | isa = XCConfigurationList; 445 | buildConfigurations = ( 446 | 78C901F519C8BFDA0042C514 /* Debug */, 447 | 78C901F619C8BFDA0042C514 /* Release */, 448 | ); 449 | defaultConfigurationIsVisible = 0; 450 | defaultConfigurationName = Release; 451 | }; 452 | /* End XCConfigurationList section */ 453 | }; 454 | rootObject = 78C901D519C8BFDA0042C514 /* Project object */; 455 | } 456 | --------------------------------------------------------------------------------