├── ObserverSet.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── ObserverSetTests ├── Info.plist ├── CaptureSemanticsTests.swift └── ObserverSetTests.swift ├── ObserverSet ├── Info.plist └── ObserverSet.swift └── LICENSE /ObserverSet.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObserverSetTests/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 | -------------------------------------------------------------------------------- /ObserverSet/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 | NSHumanReadableCopyright 24 | Copyright © 2015 Mike Ash. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ObserverSet is distributed under a BSD license, as listed below. 2 | 3 | 4 | Copyright (c) 2015, Michael Ash 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of Michael Ash nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /ObserverSetTests/CaptureSemanticsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // ObserverSet 4 | // 5 | // Created by Karl Traunmüller on 26/02/16. 6 | // Copyright © 2016 Mike Ash. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import ObserverSet 11 | 12 | class CaptureSemanticsTests: XCTestCase { 13 | 14 | class TestObservee { 15 | let event = ObserverSet() 16 | } 17 | 18 | class TestObserverThatRegistersClosure { 19 | let observee = TestObservee() 20 | 21 | init() { 22 | observee.event.add({ [weak self] () -> Void in 23 | self?.foo() 24 | }) 25 | } 26 | 27 | private func foo() { 28 | } 29 | } 30 | 31 | class TestObserverThatRegistersUnboundMemberFunction { 32 | let observee = TestObservee() 33 | 34 | init() { 35 | observee.event.add(self, self.dynamicType.voidHandler) 36 | } 37 | 38 | func voidHandler() { 39 | } 40 | } 41 | 42 | class TestObserverThatRegistersBoundMemberFunction { 43 | let observee = TestObservee() 44 | 45 | init() { 46 | observee.event.add(voidHandler) 47 | } 48 | 49 | func voidHandler() { 50 | } 51 | } 52 | 53 | func testObserverThatRegistersClosure() { 54 | weak var obj: AnyObject? = TestObserverThatRegistersClosure() 55 | XCTAssertNil(obj) 56 | } 57 | 58 | func testObserverThatRegistersUnboundMemberFunction() { 59 | weak var obj: AnyObject? = TestObserverThatRegistersUnboundMemberFunction() 60 | XCTAssertNil(obj) 61 | } 62 | 63 | // see also: 64 | // - https://devforums.apple.com/thread/237021 65 | // - https://devforums.apple.com/message/1012414#1012414 66 | func testObserverThatRegistersBoundMemberFunction() { 67 | weak var obj: AnyObject? = TestObserverThatRegistersBoundMemberFunction() 68 | XCTAssertNotNil(obj, "Registering a bound member function may result in a strong reference cycle. Use the overload of add() that takes an observer object and an unbound member function.") 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /ObserverSet/ObserverSet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObserverSet.swift 3 | // ObserverSet 4 | // 5 | // Created by Mike Ash on 1/22/15. 6 | // Copyright (c) 2015 Mike Ash. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class ObserverSetEntry { 12 | private weak var object: AnyObject? 13 | private let f: AnyObject -> Parameters -> Void 14 | 15 | private init(object: AnyObject, f: AnyObject -> Parameters -> Void) { 16 | self.object = object 17 | self.f = f 18 | } 19 | } 20 | 21 | public class ObserverSet: CustomStringConvertible { 22 | // Locking support 23 | 24 | private var queue = dispatch_queue_create("com.mikeash.ObserverSet", nil) 25 | 26 | private func synchronized(f: Void -> Void) { 27 | dispatch_sync(queue, f) 28 | } 29 | 30 | 31 | // Main implementation 32 | 33 | private var entries: [ObserverSetEntry] = [] 34 | 35 | public init() {} 36 | 37 | public func add(object: T, _ f: T -> Parameters -> Void) -> ObserverSetEntry { 38 | let entry = ObserverSetEntry(object: object, f: { f($0 as! T) }) 39 | synchronized { 40 | self.entries.append(entry) 41 | } 42 | return entry 43 | } 44 | 45 | public func add(f: Parameters -> Void) -> ObserverSetEntry { 46 | return self.add(self, { ignored in f }) 47 | } 48 | 49 | public func remove(entry: ObserverSetEntry) { 50 | synchronized { 51 | self.entries = self.entries.filter{ $0 !== entry } 52 | } 53 | } 54 | 55 | public func notify(parameters: Parameters) { 56 | var toCall: [Parameters -> Void] = [] 57 | 58 | synchronized { 59 | for entry in self.entries { 60 | if let object: AnyObject = entry.object { 61 | toCall.append(entry.f(object)) 62 | } 63 | } 64 | self.entries = self.entries.filter{ $0.object != nil } 65 | } 66 | 67 | for f in toCall { 68 | f(parameters) 69 | } 70 | } 71 | 72 | 73 | // MARK: CustomStringConvertible 74 | 75 | public var description: String { 76 | var entries: [ObserverSetEntry] = [] 77 | synchronized { 78 | entries = self.entries 79 | } 80 | 81 | let strings = entries.map{ 82 | entry in 83 | (entry.object === self 84 | ? "\(entry.f)" 85 | : "\(entry.object) \(entry.f)") 86 | } 87 | let joined = strings.joinWithSeparator(", ") 88 | 89 | return "\(Mirror(reflecting: self).description): (\(joined))" 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /ObserverSetTests/ObserverSetTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObserverSetTests.swift 3 | // ObserverSetTests 4 | // 5 | // Created by Mike Ash on 1/22/15. 6 | // Copyright (c) 2015 Mike Ash. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import XCTest 11 | 12 | import ObserverSet 13 | 14 | class ObserverSetTests: XCTestCase { 15 | class TestObservee { 16 | let voidObservers = ObserverSet() 17 | let stringObservers = ObserverSet() 18 | let twoStringObservers = ObserverSet<(String, String)>() 19 | let intObservers = ObserverSet<(Int, Int)>() 20 | let intAndStringObservers = ObserverSet<(Int, String)>() 21 | let namedParameterObservers = ObserverSet<(name: String, count: Int)>() 22 | 23 | func testNotify() { 24 | voidObservers.notify() 25 | stringObservers.notify("Sup") 26 | twoStringObservers.notify(("hello", "world")) 27 | intObservers.notify((42, 43)) 28 | intAndStringObservers.notify((42, "hello")) 29 | namedParameterObservers.notify((name: "someName", count: 42)) 30 | } 31 | } 32 | 33 | class TestObserver { 34 | init(observee: TestObservee) { 35 | observee.voidObservers.add(self, self.dynamicType.voidSent) 36 | observee.stringObservers.add(self, self.dynamicType.stringChanged) 37 | observee.twoStringObservers.add(self, self.dynamicType.twoStringChanged) 38 | observee.intObservers.add(self, self.dynamicType.intChanged) 39 | observee.intAndStringObservers.add(self, self.dynamicType.intAndStringChanged) 40 | observee.namedParameterObservers.add(self, self.dynamicType.namedParameterSent) 41 | } 42 | 43 | deinit { 44 | print("deinit!!!!") 45 | } 46 | 47 | func voidSent() { 48 | print("void sent") 49 | } 50 | 51 | func stringChanged(s: String) { 52 | print("stringChanged: " + s) 53 | } 54 | 55 | func twoStringChanged(s1: String, s2: String) { 56 | print("twoStringChanged: \(s1) \(s2)") 57 | } 58 | 59 | func intChanged(i: Int, j: Int) { 60 | print("intChanged: \(i) \(j)") 61 | } 62 | 63 | func intAndStringChanged(i: Int, s: String) { 64 | print("intAndStringChanged: \(i) \(s)") 65 | } 66 | 67 | func namedParameterSent(name: String, count: Int) { 68 | print("Named parameters: \(name) \(count)") 69 | } 70 | } 71 | 72 | func testBasics() { 73 | let observee = TestObservee() 74 | var obj: TestObserver? = TestObserver(observee: observee) 75 | 76 | let token = observee.intAndStringObservers.add{ print("int and string closure: \($0) \($1)") } 77 | print("intAndStringObservers: \(observee.intAndStringObservers.description)") 78 | 79 | observee.testNotify() 80 | print("Destroying test observer \(obj)") 81 | obj = nil 82 | observee.testNotify() 83 | observee.intAndStringObservers.remove(token) 84 | observee.testNotify() 85 | 86 | print("intAndStringObservers: \(observee.intAndStringObservers.description)") 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ObserverSet.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8E904FD01C80206600383B20 /* CaptureSemanticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E904FCF1C80206600383B20 /* CaptureSemanticsTests.swift */; }; 11 | C2CC54651A71D8610084E87D /* ObserverSet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC54591A71D8610084E87D /* ObserverSet.framework */; }; 12 | C2CC546C1A71D8610084E87D /* ObserverSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2CC546B1A71D8610084E87D /* ObserverSetTests.swift */; }; 13 | C2CC54761A71D8FE0084E87D /* ObserverSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2CC54751A71D8FE0084E87D /* ObserverSet.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXContainerItemProxy section */ 17 | C2CC54661A71D8610084E87D /* PBXContainerItemProxy */ = { 18 | isa = PBXContainerItemProxy; 19 | containerPortal = C2CC54501A71D8610084E87D /* Project object */; 20 | proxyType = 1; 21 | remoteGlobalIDString = C2CC54581A71D8610084E87D; 22 | remoteInfo = ObserverSet; 23 | }; 24 | /* End PBXContainerItemProxy section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 8E904FCF1C80206600383B20 /* CaptureSemanticsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureSemanticsTests.swift; sourceTree = ""; }; 28 | C2CC54591A71D8610084E87D /* ObserverSet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ObserverSet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | C2CC545D1A71D8610084E87D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | C2CC54641A71D8610084E87D /* ObserverSetTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObserverSetTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | C2CC546A1A71D8610084E87D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | C2CC546B1A71D8610084E87D /* ObserverSetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObserverSetTests.swift; sourceTree = ""; }; 33 | C2CC54751A71D8FE0084E87D /* ObserverSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverSet.swift; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | C2CC54551A71D8610084E87D /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | C2CC54611A71D8610084E87D /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | C2CC54651A71D8610084E87D /* ObserverSet.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | C2CC544F1A71D8610084E87D = { 56 | isa = PBXGroup; 57 | children = ( 58 | C2CC545B1A71D8610084E87D /* ObserverSet */, 59 | C2CC54681A71D8610084E87D /* ObserverSetTests */, 60 | C2CC545A1A71D8610084E87D /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | C2CC545A1A71D8610084E87D /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | C2CC54591A71D8610084E87D /* ObserverSet.framework */, 68 | C2CC54641A71D8610084E87D /* ObserverSetTests.xctest */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | C2CC545B1A71D8610084E87D /* ObserverSet */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | C2CC54751A71D8FE0084E87D /* ObserverSet.swift */, 77 | C2CC545C1A71D8610084E87D /* Supporting Files */, 78 | ); 79 | path = ObserverSet; 80 | sourceTree = ""; 81 | }; 82 | C2CC545C1A71D8610084E87D /* Supporting Files */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | C2CC545D1A71D8610084E87D /* Info.plist */, 86 | ); 87 | name = "Supporting Files"; 88 | sourceTree = ""; 89 | }; 90 | C2CC54681A71D8610084E87D /* ObserverSetTests */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | C2CC546B1A71D8610084E87D /* ObserverSetTests.swift */, 94 | 8E904FCF1C80206600383B20 /* CaptureSemanticsTests.swift */, 95 | C2CC54691A71D8610084E87D /* Supporting Files */, 96 | ); 97 | path = ObserverSetTests; 98 | sourceTree = ""; 99 | }; 100 | C2CC54691A71D8610084E87D /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | C2CC546A1A71D8610084E87D /* Info.plist */, 104 | ); 105 | name = "Supporting Files"; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXHeadersBuildPhase section */ 111 | C2CC54561A71D8610084E87D /* Headers */ = { 112 | isa = PBXHeadersBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | /* End PBXHeadersBuildPhase section */ 119 | 120 | /* Begin PBXNativeTarget section */ 121 | C2CC54581A71D8610084E87D /* ObserverSet */ = { 122 | isa = PBXNativeTarget; 123 | buildConfigurationList = C2CC546F1A71D8610084E87D /* Build configuration list for PBXNativeTarget "ObserverSet" */; 124 | buildPhases = ( 125 | C2CC54541A71D8610084E87D /* Sources */, 126 | C2CC54551A71D8610084E87D /* Frameworks */, 127 | C2CC54561A71D8610084E87D /* Headers */, 128 | C2CC54571A71D8610084E87D /* Resources */, 129 | ); 130 | buildRules = ( 131 | ); 132 | dependencies = ( 133 | ); 134 | name = ObserverSet; 135 | productName = ObserverSet; 136 | productReference = C2CC54591A71D8610084E87D /* ObserverSet.framework */; 137 | productType = "com.apple.product-type.framework"; 138 | }; 139 | C2CC54631A71D8610084E87D /* ObserverSetTests */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = C2CC54721A71D8610084E87D /* Build configuration list for PBXNativeTarget "ObserverSetTests" */; 142 | buildPhases = ( 143 | C2CC54601A71D8610084E87D /* Sources */, 144 | C2CC54611A71D8610084E87D /* Frameworks */, 145 | C2CC54621A71D8610084E87D /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | C2CC54671A71D8610084E87D /* PBXTargetDependency */, 151 | ); 152 | name = ObserverSetTests; 153 | productName = ObserverSetTests; 154 | productReference = C2CC54641A71D8610084E87D /* ObserverSetTests.xctest */; 155 | productType = "com.apple.product-type.bundle.unit-test"; 156 | }; 157 | /* End PBXNativeTarget section */ 158 | 159 | /* Begin PBXProject section */ 160 | C2CC54501A71D8610084E87D /* Project object */ = { 161 | isa = PBXProject; 162 | attributes = { 163 | LastSwiftMigration = 0720; 164 | LastSwiftUpdateCheck = 0720; 165 | LastUpgradeCheck = 0720; 166 | ORGANIZATIONNAME = "Mike Ash"; 167 | TargetAttributes = { 168 | C2CC54581A71D8610084E87D = { 169 | CreatedOnToolsVersion = 6.1.1; 170 | }; 171 | C2CC54631A71D8610084E87D = { 172 | CreatedOnToolsVersion = 6.1.1; 173 | }; 174 | }; 175 | }; 176 | buildConfigurationList = C2CC54531A71D8610084E87D /* Build configuration list for PBXProject "ObserverSet" */; 177 | compatibilityVersion = "Xcode 3.2"; 178 | developmentRegion = English; 179 | hasScannedForEncodings = 0; 180 | knownRegions = ( 181 | en, 182 | ); 183 | mainGroup = C2CC544F1A71D8610084E87D; 184 | productRefGroup = C2CC545A1A71D8610084E87D /* Products */; 185 | projectDirPath = ""; 186 | projectRoot = ""; 187 | targets = ( 188 | C2CC54581A71D8610084E87D /* ObserverSet */, 189 | C2CC54631A71D8610084E87D /* ObserverSetTests */, 190 | ); 191 | }; 192 | /* End PBXProject section */ 193 | 194 | /* Begin PBXResourcesBuildPhase section */ 195 | C2CC54571A71D8610084E87D /* Resources */ = { 196 | isa = PBXResourcesBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | C2CC54621A71D8610084E87D /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | /* End PBXResourcesBuildPhase section */ 210 | 211 | /* Begin PBXSourcesBuildPhase section */ 212 | C2CC54541A71D8610084E87D /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | C2CC54761A71D8FE0084E87D /* ObserverSet.swift in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | C2CC54601A71D8610084E87D /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | C2CC546C1A71D8610084E87D /* ObserverSetTests.swift in Sources */, 225 | 8E904FD01C80206600383B20 /* CaptureSemanticsTests.swift in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | /* End PBXSourcesBuildPhase section */ 230 | 231 | /* Begin PBXTargetDependency section */ 232 | C2CC54671A71D8610084E87D /* PBXTargetDependency */ = { 233 | isa = PBXTargetDependency; 234 | target = C2CC54581A71D8610084E87D /* ObserverSet */; 235 | targetProxy = C2CC54661A71D8610084E87D /* PBXContainerItemProxy */; 236 | }; 237 | /* End PBXTargetDependency section */ 238 | 239 | /* Begin XCBuildConfiguration section */ 240 | C2CC546D1A71D8610084E87D /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BOOL_CONVERSION = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 251 | CLANG_WARN_EMPTY_BODY = YES; 252 | CLANG_WARN_ENUM_CONVERSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 255 | CLANG_WARN_UNREACHABLE_CODE = YES; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | COPY_PHASE_STRIP = NO; 258 | CURRENT_PROJECT_VERSION = 1; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | ENABLE_TESTABILITY = YES; 261 | GCC_C_LANGUAGE_STANDARD = gnu99; 262 | GCC_DYNAMIC_NO_PIC = NO; 263 | GCC_OPTIMIZATION_LEVEL = 0; 264 | GCC_PREPROCESSOR_DEFINITIONS = ( 265 | "DEBUG=1", 266 | "$(inherited)", 267 | ); 268 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | MACOSX_DEPLOYMENT_TARGET = 10.10; 276 | MTL_ENABLE_DEBUG_INFO = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = macosx; 279 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 280 | VERSIONING_SYSTEM = "apple-generic"; 281 | VERSION_INFO_PREFIX = ""; 282 | }; 283 | name = Debug; 284 | }; 285 | C2CC546E1A71D8610084E87D /* Release */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ALWAYS_SEARCH_USER_PATHS = NO; 289 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 290 | CLANG_CXX_LIBRARY = "libc++"; 291 | CLANG_ENABLE_MODULES = YES; 292 | CLANG_ENABLE_OBJC_ARC = YES; 293 | CLANG_WARN_BOOL_CONVERSION = YES; 294 | CLANG_WARN_CONSTANT_CONVERSION = YES; 295 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 296 | CLANG_WARN_EMPTY_BODY = YES; 297 | CLANG_WARN_ENUM_CONVERSION = YES; 298 | CLANG_WARN_INT_CONVERSION = YES; 299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 300 | CLANG_WARN_UNREACHABLE_CODE = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | CURRENT_PROJECT_VERSION = 1; 304 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 305 | ENABLE_NS_ASSERTIONS = NO; 306 | ENABLE_STRICT_OBJC_MSGSEND = YES; 307 | GCC_C_LANGUAGE_STANDARD = gnu99; 308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 310 | GCC_WARN_UNDECLARED_SELECTOR = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 312 | GCC_WARN_UNUSED_FUNCTION = YES; 313 | GCC_WARN_UNUSED_VARIABLE = YES; 314 | MACOSX_DEPLOYMENT_TARGET = 10.10; 315 | MTL_ENABLE_DEBUG_INFO = NO; 316 | SDKROOT = macosx; 317 | VERSIONING_SYSTEM = "apple-generic"; 318 | VERSION_INFO_PREFIX = ""; 319 | }; 320 | name = Release; 321 | }; 322 | C2CC54701A71D8610084E87D /* Debug */ = { 323 | isa = XCBuildConfiguration; 324 | buildSettings = { 325 | CLANG_ENABLE_MODULES = YES; 326 | COMBINE_HIDPI_IMAGES = YES; 327 | DEFINES_MODULE = YES; 328 | DYLIB_COMPATIBILITY_VERSION = 1; 329 | DYLIB_CURRENT_VERSION = 1; 330 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 331 | FRAMEWORK_VERSION = A; 332 | INFOPLIST_FILE = ObserverSet/Info.plist; 333 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 334 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 335 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.$(PRODUCT_NAME:rfc1034identifier)"; 336 | PRODUCT_NAME = "$(TARGET_NAME)"; 337 | SKIP_INSTALL = YES; 338 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 339 | }; 340 | name = Debug; 341 | }; 342 | C2CC54711A71D8610084E87D /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | CLANG_ENABLE_MODULES = YES; 346 | COMBINE_HIDPI_IMAGES = YES; 347 | DEFINES_MODULE = YES; 348 | DYLIB_COMPATIBILITY_VERSION = 1; 349 | DYLIB_CURRENT_VERSION = 1; 350 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 351 | FRAMEWORK_VERSION = A; 352 | INFOPLIST_FILE = ObserverSet/Info.plist; 353 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 355 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.$(PRODUCT_NAME:rfc1034identifier)"; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | SKIP_INSTALL = YES; 358 | }; 359 | name = Release; 360 | }; 361 | C2CC54731A71D8610084E87D /* Debug */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | COMBINE_HIDPI_IMAGES = YES; 365 | FRAMEWORK_SEARCH_PATHS = ( 366 | "$(DEVELOPER_FRAMEWORKS_DIR)", 367 | "$(inherited)", 368 | ); 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | INFOPLIST_FILE = ObserverSetTests/Info.plist; 374 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 375 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.$(PRODUCT_NAME:rfc1034identifier)"; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | }; 378 | name = Debug; 379 | }; 380 | C2CC54741A71D8610084E87D /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | COMBINE_HIDPI_IMAGES = YES; 384 | FRAMEWORK_SEARCH_PATHS = ( 385 | "$(DEVELOPER_FRAMEWORKS_DIR)", 386 | "$(inherited)", 387 | ); 388 | INFOPLIST_FILE = ObserverSetTests/Info.plist; 389 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 390 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.$(PRODUCT_NAME:rfc1034identifier)"; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | }; 393 | name = Release; 394 | }; 395 | /* End XCBuildConfiguration section */ 396 | 397 | /* Begin XCConfigurationList section */ 398 | C2CC54531A71D8610084E87D /* Build configuration list for PBXProject "ObserverSet" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | C2CC546D1A71D8610084E87D /* Debug */, 402 | C2CC546E1A71D8610084E87D /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | C2CC546F1A71D8610084E87D /* Build configuration list for PBXNativeTarget "ObserverSet" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | C2CC54701A71D8610084E87D /* Debug */, 411 | C2CC54711A71D8610084E87D /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | C2CC54721A71D8610084E87D /* Build configuration list for PBXNativeTarget "ObserverSetTests" */ = { 417 | isa = XCConfigurationList; 418 | buildConfigurations = ( 419 | C2CC54731A71D8610084E87D /* Debug */, 420 | C2CC54741A71D8610084E87D /* Release */, 421 | ); 422 | defaultConfigurationIsVisible = 0; 423 | defaultConfigurationName = Release; 424 | }; 425 | /* End XCConfigurationList section */ 426 | }; 427 | rootObject = C2CC54501A71D8610084E87D /* Project object */; 428 | } 429 | --------------------------------------------------------------------------------