├── logo.png ├── Eki-iOS.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── Eki.xcscheme └── project.pbxproj ├── .gitignore ├── Eki ├── Once.swift ├── Eki.h ├── Info.plist ├── Task.swift ├── Group.swift ├── Semaphore.swift ├── Timer.swift └── Queue.swift ├── EkiTests ├── Info.plist └── EkiTests.swift ├── LICENSE ├── Eki.podspec ├── Eki-OSX.xcodeproj ├── xcshareddata │ └── xcschemes │ │ └── Eki.xcscheme └── project.pbxproj └── README.md /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kodlian/Eki/HEAD/logo.png -------------------------------------------------------------------------------- /Eki-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _Store 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | *.o 19 | */Iconr -------------------------------------------------------------------------------- /Eki/Once.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Once.swift 3 | // Eki 4 | // 5 | // Created by Jeremy Marchand on 20/10/2014. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Create a block that dispatch a block once and only once. 13 | */ 14 | public func OnceDispatcher() -> ((() -> Void) -> Void) { 15 | var token = dispatch_once_t(0) 16 | 17 | return { block in 18 | dispatch_once(&token, block) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eki/Eki.h: -------------------------------------------------------------------------------- 1 | // 2 | // Eki.h 3 | // Eki 4 | // 5 | // Created by Jérémy Marchand on 15/10/14. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Eki. 12 | FOUNDATION_EXPORT double EkiVersionNumber; 13 | 14 | //! Project version string for Eki. 15 | FOUNDATION_EXPORT const unsigned char EkiVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /EkiTests/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 | -------------------------------------------------------------------------------- /Eki/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 © 2014 Jérémy Marchand. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jeremy Marchand (kodlian.com) 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 | -------------------------------------------------------------------------------- /Eki.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 4 | 5 | s.name = "Eki" 6 | s.version = "2.0.0" 7 | s.summary = "Eki lets you manage easily concurrency in your apps. This framework make Grand Central Dispatch API more friendly and fun to use." 8 | 9 | s.homepage = "https://github.com/kodlian/eki" 10 | 11 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | 13 | s.license = "MIT" 14 | 15 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 16 | 17 | s.author = "Jérémy Marchand" 18 | s.social_media_url = "http://twitter.com/kodlian" 19 | 20 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 21 | 22 | # When using multiple platforms 23 | s.ios.deployment_target = "8.0" 24 | s.osx.deployment_target = "10.10" 25 | 26 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 27 | 28 | s.source = { :git => "https://github.com/kodlian/eki.git", :tag => "2.0.0" } 29 | 30 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 31 | 32 | s.source_files = "Eki/**/*.swift" 33 | 34 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 35 | 36 | s.resource = "logo.png" 37 | 38 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 39 | 40 | 41 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 42 | 43 | 44 | end 45 | -------------------------------------------------------------------------------- /Eki/Task.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Task.swift 3 | // Eki 4 | // 5 | // Created by Jeremy Marchand on 20/10/2014. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Chainable type 13 | */ 14 | public protocol Chainable { 15 | func chain(block:() -> Void) -> Chainable 16 | func chain(task: Task) -> Chainable 17 | } 18 | 19 | /** 20 | A task is defined by a queue and a block 21 | */ 22 | public class Task: Chainable { 23 | public let queue: Queue 24 | internal let dispatchBlock: dispatch_block_t 25 | public var block:() -> Void { return dispatchBlock } 26 | 27 | public init(queue: Queue = Queue.Background, block:() -> Void) { 28 | self.queue = queue 29 | self.dispatchBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, block) 30 | } 31 | private init(queue: Queue = Queue.Background, dispatchBlock: dispatch_block_t) { 32 | self.queue = queue 33 | self.dispatchBlock = dispatchBlock 34 | } 35 | 36 | //MARK: - Dispatch 37 | public func async() -> Chainable { 38 | queue.async(dispatchBlock) 39 | return self 40 | } 41 | public func sync() -> Chainable { 42 | queue.sync(dispatchBlock) 43 | return self 44 | } 45 | public func cancel() { 46 | dispatch_block_cancel(dispatchBlock) 47 | } 48 | 49 | //MARK: - Chain 50 | public func chain(task: Task) -> Chainable { 51 | dispatch_block_notify(self.dispatchBlock, task.queue.dispatchQueue, task.dispatchBlock) 52 | return task 53 | } 54 | public func chain(block:() -> Void) -> Chainable { 55 | let task = Task(queue: queue, block: block) 56 | return chain(task) 57 | } 58 | } 59 | 60 | //MARK: Operator 61 | infix operator <> {associativity left precedence 110} 62 | public func <> (c: Chainable, block:() -> Void) -> Chainable { 63 | return c.chain(block) 64 | } 65 | public func <> (c: Chainable, task: Task) -> Chainable { 66 | return c.chain(task) 67 | } 68 | 69 | public func + (q: Queue, block:() -> Void) -> Task { 70 | return Task(queue: q, block: block) 71 | } 72 | -------------------------------------------------------------------------------- /Eki/Group.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Group.swift 3 | // Eki 4 | // 5 | // Created by Jeremy Marchand on 20/10/2014. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | A wrapper for Grand Central Dispatch Group 13 | */ 14 | public class Group { 15 | private var group = dispatch_group_create() 16 | public var queue: Queue = Queue.UserInitiated 17 | 18 | public init(queue: Queue = Queue.Background) { 19 | self.queue = queue 20 | } 21 | 22 | public convenience init(tasks: [Task]) { 23 | self.init() 24 | async(tasks) 25 | } 26 | 27 | //MARK: Dispatch 28 | public func async(block:() -> Void) -> Group { 29 | return async(queue + block) 30 | } 31 | public func async(task: Task) -> Group { 32 | dispatch_group_async(group, task.queue.dispatchQueue, task.dispatchBlock) 33 | return self 34 | } 35 | 36 | public func async(blocks:[() -> Void]) -> Group { 37 | async(blocks.map { self.queue + $0 }) 38 | return self 39 | } 40 | public func async(tasks: [Task]) -> Group { 41 | for task in tasks { 42 | async(task) 43 | } 44 | return self 45 | } 46 | 47 | //MARK: - Manually 48 | public func enter() { 49 | dispatch_group_enter(group) 50 | } 51 | public func leave() { 52 | dispatch_group_leave(group) 53 | } 54 | 55 | //MARK: Others 56 | public func notify(block:() -> Void) -> Group { 57 | return notify(queue + block) 58 | } 59 | public func notify(task: Task) -> Group { 60 | dispatch_group_notify(group, task.queue.dispatchQueue, task.dispatchBlock) 61 | return self 62 | } 63 | 64 | public func wait(time: NSTimeInterval? = nil) -> Bool { 65 | return dispatch_group_wait(group, dispatch_time_t(timeInterval: time)) == 0 66 | } 67 | 68 | 69 | } 70 | 71 | //MARK: Operator 72 | public func <<< (g: Group, block:() -> Void) -> Group { 73 | return g.async(block) 74 | } 75 | public func <<< (g: Group, task: Task) -> Group { 76 | return g.async(task) 77 | } 78 | public func <<< (g: Group, blocks:[() -> Void]) -> Group { 79 | return g.async(blocks) 80 | } 81 | public func <<< (g: Group, tasks: [Task]) -> Group { 82 | return g.async(tasks) 83 | } 84 | public postfix func ++ (group: Group) { 85 | group.enter() 86 | } 87 | public postfix func -- (group: Group) { 88 | group.leave() 89 | } 90 | -------------------------------------------------------------------------------- /Eki/Semaphore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Semaphore.swift 3 | // Eki 4 | // 5 | // Created by Jeremy Marchand on 14/05/2015. 6 | // Copyright (c) 2015 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | /** 11 | A wrapper for Grand Central Dispatch Semaphore 12 | */ 13 | public struct Semaphore { 14 | public enum Kind { 15 | case Binary 16 | case Barrier 17 | case Counting(resource:UInt16) 18 | 19 | func unitsCount() -> Int { 20 | switch self { 21 | case Binary: 22 | return 1 23 | case Barrier: 24 | return 0 25 | case Counting(let c): 26 | return Int(c) 27 | } 28 | } 29 | } 30 | 31 | private let semaphore: dispatch_semaphore_t 32 | private let kind: Kind 33 | 34 | public init(_ kind: Kind = .Binary) { 35 | self.kind = kind 36 | semaphore = dispatch_semaphore_create(kind.unitsCount()) 37 | } 38 | public init(resource: UInt16) { 39 | self.kind = .Counting(resource:resource) 40 | semaphore = dispatch_semaphore_create(kind.unitsCount()) 41 | } 42 | 43 | //MARK: - Semaphore core method 44 | public func wait(time someTime: NSTimeInterval? = nil) -> Bool { 45 | let dispatchTime: dispatch_time_t 46 | 47 | if let time = someTime { 48 | dispatchTime = dispatch_time( 49 | DISPATCH_TIME_NOW, 50 | Int64(time.nanosecondsRepresentation)) 51 | } else { 52 | dispatchTime = DISPATCH_TIME_FOREVER 53 | } 54 | 55 | return dispatch_semaphore_wait(semaphore, dispatchTime) == 0 56 | } 57 | 58 | public func signal() -> Bool { 59 | return dispatch_semaphore_signal(semaphore) > 0 60 | } 61 | 62 | 63 | } 64 | 65 | //MARK: - Convenient method to perform a block when a semaphore resource is free and immediatly release it after the block execution. 66 | public extension Semaphore { 67 | public func perform(block: (Void) -> Void) { 68 | wait() 69 | block() 70 | signal() 71 | } 72 | } 73 | 74 | //MARK: - Edsger Dijkstra naming - Dutch 75 | public extension Semaphore { 76 | public func P(time time: NSTimeInterval? = nil) -> Bool { 77 | return self.wait(time: time) 78 | } 79 | public func V() -> Bool { 80 | return self.signal() 81 | } 82 | } 83 | 84 | /** 85 | A Mutex is essentially the same thing as a binary semaphore exept that only the block that locked the mutext is supposed to unlock it. 86 | */ 87 | public struct Mutex { 88 | private var semaphore: Semaphore 89 | 90 | public init() { 91 | semaphore = Semaphore(.Binary) 92 | } 93 | 94 | public func sync(block: (Void) -> Void) { 95 | semaphore.perform(block) 96 | } 97 | 98 | } 99 | 100 | /** 101 | Convenient class to lock access to an object with an internal mutext 102 | */ 103 | public struct LockedObject { 104 | private var object: T 105 | private var mutext: Mutex 106 | init(_ object: T) { 107 | self.object = object 108 | mutext = Mutex() 109 | } 110 | func access(block:(object: T) -> Void) { 111 | mutext.sync { (Void) -> Void in 112 | block(object: self.object) 113 | } 114 | } 115 | } 116 | 117 | //MARK: Operator 118 | public func <<< (semaphore: Semaphore, block:() -> Void) -> Semaphore { 119 | semaphore.perform(block) 120 | return semaphore 121 | } 122 | public postfix func ++ (semaphore: Semaphore) { 123 | semaphore.signal() 124 | } 125 | public postfix func -- (semaphore: Semaphore) { 126 | semaphore.wait() 127 | } 128 | public func <<< (mutex: Mutex, block:() -> Void) -> Mutex { 129 | mutex.sync(block) 130 | return mutex 131 | } 132 | public func <<< (l: LockedObject, block: (object: T) -> Void) -> LockedObject { 133 | l.access(block) 134 | return l 135 | } 136 | -------------------------------------------------------------------------------- /Eki-OSX.xcodeproj/xcshareddata/xcschemes/Eki.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Eki-iOS.xcodeproj/xcshareddata/xcschemes/Eki.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /EkiTests/EkiTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EkiTests.swift 3 | // EkiTests 4 | // 5 | // Created by Jérémy Marchand on 15/10/14. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import Eki 12 | 13 | class EkiTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | } 19 | 20 | override func tearDown() { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | super.tearDown() 23 | } 24 | 25 | func testAsync() { 26 | let expt = self.expectationWithDescription("Dispatch") 27 | 28 | Queue.Background <<< { 29 | 30 | } <<< { 31 | expt.fulfill() 32 | } 33 | 34 | self.waitForExpectationsWithTimeout(2, handler: nil) 35 | } 36 | 37 | func testCustomAsync() { 38 | let expt = self.expectationWithDescription("CustomAsync") 39 | let q = Queue(name: "foo", kind: .Concurrent) 40 | var a = 0 41 | 42 | q <<< { 43 | a++ 44 | } |<| { 45 | if a == 1 { 46 | a++ 47 | } 48 | } <<< { 49 | expt.fulfill() 50 | XCTAssertEqual(a, 2, "Block barrier have not been executed correctly") 51 | 52 | } 53 | self.waitForExpectationsWithTimeout(2, handler: nil) 54 | } 55 | 56 | func testIterate() { 57 | let expt = self.expectationWithDescription("Iterate") 58 | 59 | var c = 0 60 | Queue.UserInitiated.iterate(4) { i in 61 | c++ 62 | if c == 4 { 63 | expt.fulfill() 64 | } 65 | } 66 | 67 | 68 | self.waitForExpectationsWithTimeout(2, handler: nil) 69 | } 70 | 71 | func testTaskChain() { 72 | let expt = self.expectationWithDescription("Operation") 73 | 74 | var test = [0,0] 75 | let task = Queue.UserInitiated + { 76 | test[0] = 1 77 | } 78 | 79 | task.async() <> { 80 | test = test.reverse() 81 | } <> Queue.Main + { 82 | expt.fulfill() 83 | XCTAssertEqual(test, [0,1], "Blocks have not been executed on a chain") 84 | } 85 | 86 | 87 | 88 | self.waitForExpectationsWithTimeout(4, handler: nil) 89 | } 90 | 91 | func testOnce() { 92 | let once = OnceDispatcher() 93 | var c = 0 94 | for _ in 0...4 { 95 | once { 96 | c++ 97 | } 98 | } 99 | 100 | XCTAssertEqual(c, 1, "Block have not been executed one time") 101 | } 102 | 103 | func testGroup() { 104 | let expt = self.expectationWithDescription("Group") 105 | 106 | var test = [0,0,0,0] 107 | let queue = Queue(name: "myqueue", kind: .Concurrent) 108 | let grp = Group(queue: queue) 109 | for i in 0..<4 { 110 | grp <<< { 111 | test[i] = i 112 | } 113 | } 114 | grp.notify { 115 | expt.fulfill() 116 | XCTAssertEqual(test, [0,1,2,3], "GRoup 's blocks have not been executed correctly") 117 | 118 | } 119 | 120 | self.waitForExpectationsWithTimeout(4, handler: nil) 121 | 122 | } 123 | 124 | 125 | func testIsCurrentOnBackground() { 126 | let expt = self.expectationWithDescription("testIsCurrentOnBackground") 127 | 128 | Queue.Background.async { () -> Void in 129 | XCTAssertTrue(Queue.Background.isCurrent, "Background should be current") 130 | XCTAssertFalse(Queue.Main.isCurrent, "Main should not be current") 131 | expt.fulfill() 132 | } 133 | 134 | 135 | self.waitForExpectationsWithTimeout(4, handler: nil) 136 | } 137 | 138 | func testIsCurrentOnCustom() { 139 | let expt = self.expectationWithDescription("testIsCurrentOnCustom") 140 | let q = Queue(name: "myqueue", kind: .Concurrent) 141 | 142 | q.async { () -> Void in 143 | XCTAssertTrue(q.isCurrent, "The custom queue should be current") 144 | XCTAssertFalse(Queue.Main.isCurrent, "Main should not be current") 145 | expt.fulfill() 146 | } 147 | 148 | 149 | self.waitForExpectationsWithTimeout(4, handler: nil) 150 | } 151 | 152 | func testCurrentQueue() { 153 | let expt = self.expectationWithDescription("testCurrentQueue") 154 | 155 | Queue.Background.async { () -> Void in 156 | let current = Queue.current 157 | switch current { 158 | case Queue.Background: 159 | do { 160 | 161 | } 162 | default: 163 | XCTFail("current should be background") 164 | } 165 | 166 | Queue.current.async { 167 | XCTAssertTrue(Queue.Background.isCurrent, "Background should be current") 168 | expt.fulfill() 169 | } 170 | } 171 | 172 | self.waitForExpectationsWithTimeout(4, handler: nil) 173 | } 174 | 175 | func testCurrentQueueOnCustom() { 176 | let expt = self.expectationWithDescription("testCurrentQueue") 177 | let q = Queue(name: "myqueue", kind: .Concurrent) 178 | 179 | q.async { () -> Void in 180 | 181 | Queue.current.async { 182 | XCTAssertTrue(q.isCurrent, "The custom queue should be current") 183 | expt.fulfill() 184 | } 185 | } 186 | 187 | self.waitForExpectationsWithTimeout(4, handler: nil) 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Eki/Timer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Timer.swift 3 | // Eki 4 | // 5 | // Created by Jeremy Marchand on 20/10/2014. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | A wrapper for Grand Central Dispatch Source Type Timer 13 | */ 14 | public final class Timer { 15 | 16 | //MARK: factory 17 | public class func scheduleWithInterval(interval: NSTimeInterval, onQueue queue: Queue, byRepeating shouldRepeat: Bool = false, block: () -> Void) -> Timer { 18 | let timer = Timer(queue: queue, interval: interval, shouldRepeat: shouldRepeat) 19 | 20 | timer.block = block 21 | timer.start() 22 | 23 | return timer 24 | } 25 | 26 | public class func scheduleWithDate(date: NSDate, onQueue queue: Queue, block: () -> Void) -> Timer { 27 | let timer = Timer(queue: queue, date: date) 28 | 29 | timer.block = block 30 | timer.start() 31 | 32 | return timer 33 | } 34 | 35 | //MARK: Properties 36 | public let queue: Queue 37 | private let source: dispatch_source_t 38 | 39 | private let syncQueue = Queue(name: "Timer.syncQueue", kind: .Serial) 40 | private var suspended = false 41 | 42 | //MARK: Timer setter 43 | public var startTime: TimeConvertible = 0 { 44 | didSet { 45 | startDispatchTime = startTime.dispatchTime 46 | updateSourceTimer() 47 | } 48 | } 49 | private var startDispatchTime: dispatch_time_t = 0 50 | 51 | 52 | public var repeatInterval: NSTimeInterval? = nil { 53 | didSet { 54 | if repeatInterval != oldValue { 55 | updateSourceTimer() 56 | } 57 | } 58 | } 59 | public var tolerance: NSTimeInterval = 0.0 { 60 | didSet { 61 | if tolerance != oldValue { 62 | updateSourceTimer() 63 | } 64 | } 65 | } 66 | 67 | private func updateSourceTimer() { 68 | let deltaTime: UInt64 69 | if let interval = repeatInterval { 70 | deltaTime = UInt64(interval * NSTimeInterval(NSEC_PER_SEC)) 71 | } else { 72 | deltaTime = DISPATCH_TIME_FOREVER 73 | } 74 | dispatch_source_set_timer( 75 | source, 76 | startDispatchTime, 77 | deltaTime, 78 | UInt64(tolerance * NSTimeInterval(NSEC_PER_SEC))) 79 | } 80 | 81 | //MARK: Handler setter 82 | public var block: (() -> Void)? = nil { 83 | didSet { 84 | updateHandler(dispatch_source_set_event_handler, handler: block) 85 | } 86 | } 87 | 88 | public var cancelHandler: (() -> Void)? = nil { 89 | didSet { 90 | updateHandler(dispatch_source_set_cancel_handler, handler: cancelHandler) 91 | } 92 | } 93 | 94 | public var startHandler: (() -> Void)? = nil { 95 | didSet { 96 | updateHandler(dispatch_source_set_registration_handler, handler: startHandler) 97 | } 98 | } 99 | 100 | private func updateHandler(handlerSetMethod:(source: dispatch_source_t, handler: dispatch_block_t!) -> Void, handler someHandler:(() -> Void)?) { 101 | let handler = someHandler != nil ? someHandler : { () -> Void in } 102 | 103 | handlerSetMethod(source: source, handler: handler) 104 | } 105 | 106 | //MARK: init 107 | private init(queue: Queue) { 108 | self.queue = queue 109 | source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue.dispatchQueue) 110 | } 111 | 112 | convenience public init(queue: Queue, interval: NSTimeInterval, shouldRepeat: Bool = false) { 113 | self.init(queue: queue) 114 | startTime = interval 115 | if shouldRepeat { 116 | repeatInterval = interval 117 | } 118 | 119 | startDispatchTime = startTime.dispatchTime 120 | updateSourceTimer() 121 | } 122 | 123 | convenience public init(queue: Queue, interval: NSTimeInterval, repeatInterval rInterval: NSTimeInterval? = nil) { 124 | self.init(queue: queue) 125 | startTime = interval 126 | repeatInterval = rInterval 127 | startDispatchTime = startTime.dispatchTime 128 | updateSourceTimer() 129 | } 130 | 131 | convenience public init(queue: Queue, date: NSDate) { 132 | self.init(queue: queue) 133 | startTime = date 134 | startDispatchTime = startTime.dispatchTime 135 | updateSourceTimer() 136 | } 137 | 138 | deinit { 139 | block = nil 140 | startHandler = nil 141 | cancelHandler = nil 142 | 143 | if !stopped { 144 | stop() 145 | } 146 | } 147 | 148 | //MARK: Suspend & Resume 149 | public func start() { 150 | syncQueue.sync { 151 | let suspended = self.suspended 152 | if suspended { 153 | self.suspended = false 154 | dispatch_resume(self.source) 155 | } 156 | } 157 | } 158 | 159 | public func pause() { 160 | syncQueue.sync { 161 | let suspended = self.suspended 162 | if !suspended { 163 | self.suspended = true 164 | dispatch_suspend(self.source) 165 | } 166 | } 167 | } 168 | 169 | public var isRunning: Bool { 170 | var isSuspended = false 171 | syncQueue.sync { 172 | isSuspended = self.suspended 173 | } 174 | return !isSuspended 175 | } 176 | 177 | //MARK: cancel 178 | public func stop() { 179 | dispatch_source_cancel(source) 180 | } 181 | 182 | var stopped: Bool { 183 | return 0 != dispatch_source_testcancel(source) 184 | } 185 | } 186 | 187 | //MARK: Time 188 | public protocol TimeConvertible { 189 | var dispatchTime: dispatch_time_t { get } 190 | } 191 | 192 | extension NSTimeInterval: TimeConvertible { 193 | public var dispatchTime: dispatch_time_t { 194 | let deltaTime = self * NSTimeInterval(NSEC_PER_SEC) 195 | return dispatch_time(DISPATCH_TIME_NOW, Int64(deltaTime)) 196 | } 197 | } 198 | 199 | private extension NSTimeInterval { 200 | private var timeSpec: timespec { 201 | var seconds: NSTimeInterval = 0.0 202 | let nanoSeconds = modf(self, &seconds) * NSTimeInterval(NSEC_PER_SEC) 203 | return timespec(tv_sec: __darwin_time_t(seconds), tv_nsec: Int(nanoSeconds)) 204 | } 205 | } 206 | 207 | extension NSDate: TimeConvertible { 208 | public var dispatchTime: dispatch_time_t { 209 | var walltime = self.timeIntervalSince1970.timeSpec 210 | return dispatch_walltime(&walltime, 0) 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /Eki/Queue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dispatch.swift 3 | // Montparnasse 4 | // 5 | // Created by Jérémy Marchand on 15/10/14. 6 | // Copyright (c) 2014 Jérémy Marchand. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | A wrapper for Grand Central Dispatch Queue 13 | */ 14 | 15 | public enum Queue { 16 | private static var currentKey = 0 17 | private static var onceSpecifics = OnceDispatcher() 18 | 19 | case Main 20 | case UserInteractive 21 | case UserInitiated 22 | case Default 23 | case Utility 24 | case Background 25 | case Custom(queue:dispatch_queue_t) 26 | 27 | private static let allDefaults: [Queue] = [Main, UserInteractive, UserInitiated, Default, Utility, Background] 28 | 29 | //MARK: type 30 | /** 31 | Customn queue type 32 | */ 33 | 34 | public enum Kind { 35 | case Concurrent, Serial 36 | 37 | func createDispatchQueueWithName(name: String) -> dispatch_queue_t { 38 | var type: dispatch_queue_attr_t! 39 | 40 | switch self { 41 | case .Concurrent: 42 | type = DISPATCH_QUEUE_CONCURRENT 43 | case .Serial: 44 | type = DISPATCH_QUEUE_SERIAL 45 | } 46 | 47 | return dispatch_queue_create(name, type) 48 | } 49 | } 50 | 51 | //MARK: init 52 | public init(name: String, kind: Kind) { 53 | self = .Custom(queue: kind.createDispatchQueueWithName(name)) 54 | setCurrentSpecific() 55 | } 56 | 57 | //MARK: Dispatch single block 58 | public func async(block: () -> Void) -> Queue { 59 | dispatch_async(dispatchQueue, block) 60 | return self 61 | } 62 | 63 | public func sync(block: () -> Void) -> Queue { 64 | if unsafeIsCurrent { 65 | block() 66 | } else { 67 | dispatch_sync(dispatchQueue, block) 68 | } 69 | return self 70 | } 71 | 72 | public func after(delay: NSTimeInterval, doBlock block: () -> Void) -> Queue { 73 | dispatch_after(dispatch_time( 74 | DISPATCH_TIME_NOW, 75 | Int64(delay.nanosecondsRepresentation) 76 | ), dispatchQueue, block) 77 | return self 78 | } 79 | 80 | public func barrierAsync(block: () -> Void) -> Queue { 81 | dispatch_barrier_async(dispatchQueue, block) 82 | return self 83 | } 84 | 85 | public func barrierSync(block: () -> Void) -> Queue { 86 | if unsafeIsCurrent { 87 | assertionFailure("You can't send a barrier on the same queue.") 88 | } else { 89 | dispatch_barrier_sync(dispatchQueue, block) 90 | } 91 | return self 92 | } 93 | 94 | //MARK: Dispatch multiple blocks 95 | public func async(blocks: [() -> Void]) -> Queue { 96 | 97 | for block in blocks { 98 | async(block) 99 | } 100 | return self 101 | } 102 | 103 | //MARK: Others 104 | public func iterate(iteration: Int, block: (i: Int) -> ()) { 105 | dispatch_apply(iteration, dispatchQueue, block) 106 | } 107 | 108 | internal var dispatchQueue: dispatch_queue_t { 109 | switch (self) { 110 | case .Main: 111 | return dispatch_get_main_queue() 112 | case .UserInteractive: 113 | return dispatch_get_global_queue(Int(QOS_CLASS_USER_INTERACTIVE.rawValue), 0) 114 | case .UserInitiated: 115 | return dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0) 116 | case .Default: 117 | return dispatch_get_global_queue(Int(QOS_CLASS_DEFAULT.rawValue), 0) 118 | case .Utility: 119 | return dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.rawValue), 0) 120 | case .Background: 121 | return dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.rawValue), 0) 122 | case .Custom(let queue): 123 | return queue 124 | } 125 | } 126 | 127 | //MARK: Suspend & Resume 128 | public func suspend() { 129 | switch (self) { 130 | case .Custom(let queue): 131 | dispatch_suspend(queue) 132 | default: 133 | assertionFailure("You can't suspend a global queue") 134 | } 135 | } 136 | 137 | public func resume() { 138 | switch (self) { 139 | case .Custom(let queue): 140 | dispatch_resume(queue) 141 | default: 142 | assertionFailure("You can't resume a global queue") 143 | } 144 | } 145 | 146 | //MARK: Current Queuess 147 | private static func initOnceGlobalQueueSpecifics() { 148 | onceSpecifics { 149 | () -> Void in 150 | for q in Queue.allDefaults { 151 | q.setCurrentSpecific() 152 | } 153 | } 154 | } 155 | 156 | private func setCurrentSpecific() { 157 | let q = dispatchQueue 158 | let opPtr = Unmanaged < dispatch_queue_t>.passUnretained(q).toOpaque() 159 | dispatch_queue_set_specific(q, 160 | &Queue.currentKey, UnsafeMutablePointer(opPtr), nil) 161 | } 162 | 163 | private static func getCurrentPointer() -> UnsafeMutablePointer { 164 | let currentPtr = dispatch_get_specific(&Queue.currentKey) 165 | // 166 | return currentPtr 167 | } 168 | 169 | public var isCurrent: Bool { 170 | Queue.initOnceGlobalQueueSpecifics() 171 | 172 | let queuePtr = dispatch_queue_get_specific(self.dispatchQueue, &Queue.currentKey) 173 | let currentPointer = Queue.getCurrentPointer() 174 | assert(currentPointer != nil, "Use only with custom queues initialized with Queue(name:String, kind:Queue.Custom.Kind), the Main queue and Global queues") 175 | return currentPointer == queuePtr 176 | } 177 | 178 | public var unsafeIsCurrent: Bool { 179 | Queue.initOnceGlobalQueueSpecifics() 180 | 181 | let queuePtr = dispatch_queue_get_specific(self.dispatchQueue, &Queue.currentKey) 182 | let currentPointer = Queue.getCurrentPointer() 183 | return currentPointer == queuePtr 184 | } 185 | public static var current: Queue { 186 | initOnceGlobalQueueSpecifics() 187 | 188 | let currentQueue = Unmanaged < dispatch_queue_t>.fromOpaque(COpaquePointer(getCurrentPointer())).takeUnretainedValue() 189 | 190 | for q in Queue.allDefaults { 191 | if q.dispatchQueue === currentQueue { 192 | return q 193 | } 194 | } 195 | 196 | return Queue.Custom(queue: currentQueue) 197 | } 198 | } 199 | 200 | //MARK: Operator 201 | infix operator <<< { associativity left precedence 160 } 202 | 203 | public func <<<(q: Queue, block: () -> Void) -> Queue { 204 | return q.async(block) 205 | } 206 | 207 | public func <<<(q: Queue, blocks: [() -> Void]) -> Queue { 208 | return q.async(blocks) 209 | } 210 | infix operator |<| { associativity left precedence 160 } 211 | 212 | public func |<|(q: Queue, block: () -> Void) -> Queue { 213 | return q.barrierAsync(block) 214 | } 215 | 216 | //MARK: Time 217 | 218 | extension NSTimeInterval { 219 | var nanosecondsRepresentation: Double { 220 | return self * Double(NSEC_PER_SEC) 221 | } 222 | } 223 | 224 | extension dispatch_time_t { 225 | init(timeInterval: NSTimeInterval?) { 226 | if let i = timeInterval { 227 | self.init(i.nanosecondsRepresentation) 228 | } else { 229 | self.init(DISPATCH_TIME_FOREVER) 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # DEPRECATED Eki # Swift 3+ offer a new elegant api for dispatch that makes EKI useless 3 | 4 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat 5 | )](http://mit-license.org) 6 | [![Platform](http://img.shields.io/badge/platform-iOS%20%26%20OSX-lightgrey.svg?style=flat 7 | )](https://developer.apple.com/resources/) 8 | [![Language](http://img.shields.io/badge/language-swift-orange.svg?style=flat 9 | )](https://developer.apple.com/swift) 10 | [![Issues](https://img.shields.io/github/issues/kodlian/Eki.svg?style=flat 11 | )](https://github.com/kodlian/Eki/issues) 12 | [![Cocoapod](http://img.shields.io/cocoapods/v/Eki.svg?style=flat)](http://cocoadocs.org/docsets/Eki/) 13 | [![Reference Status](https://www.versioneye.com/objective-c/eki/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/eki/references) 14 | 15 |

16 | logo 17 |

18 | Eki lets you manage easily concurrency in your apps. This framework makes Grand Central Dispatch easy and fun to use. 19 |

20 | 21 | ## Requirements 22 | - iOS 8.0+ / Mac OS X 10.10+ 23 | - Xcode 6.3 24 | 25 | ## Queue 26 | Internally GCD manages a pool of threads which process dispatch queues and invoke blocks submitted to them. 27 | 28 | ### Main and Global queues 29 | 30 | - `Main` 31 | - `UserInteractive` 32 | - `UserInitiated` 33 | - `Default` 34 | - `Utility` 35 | - `Background` 36 | 37 | The queues are ordered in descending priority order. 38 | 39 | You access them like so: 40 | 41 | ```swift 42 | Queue.Background 43 | ``` 44 | 45 | ### Dispatch 46 | You dispatch a block on queue asynchronously by using `async` or synchronously by using `sync`: 47 | 48 | ```swift 49 | // Asynchronously 50 | Queue.Utility.async { 51 | ... 52 | } 53 | // Or asynchronously using the operator shortcut 54 | Queue.Utility <<< { 55 | ... 56 | } 57 | 58 | // Synchronously 59 | Queue.Utility.sync { // Eki will prevent deadlock if you submit a sync on the current queue 60 | ... 61 | } 62 | ``` 63 | 64 | You can send multiple blocks to a queue: 65 | ```swift 66 | Queue.Utility.async { 67 | // Block 1 68 | }.async { 69 | // Block 2 70 | } 71 | // Or by submitting an array of blocks: 72 | let blocks = [{ 73 | // Block 1 74 | }, { 75 | // Block 2 76 | }] 77 | Queue.Utility.async(blocks) 78 | ``` 79 | 80 | 81 | ### Custom Queue 82 | 83 | Create your own queue (serial or concurrent): 84 | 85 | ```swift 86 | let queue = Queue(name:"QueueName", kind:.Concurrent) 87 | queue.async{ 88 | ... 89 | } 90 | ``` 91 | 92 | ### Dispatch barrier 93 | Dispatch a block asynchronously with barrier: 94 | 95 | ```swift 96 | let queue:Queue = Queue(name:"QueueName", type:.Concurrent) 97 | ... 98 | queue.barrierAsync { // Or operator |<| 99 | // This block will be executed on the queue only after all previous submitted blocks have been executed 100 | }.barrierAsync { 101 | // This block will be executed only after the previous barrier block have completed 102 | } 103 | ``` 104 | ### Schedule 105 | 106 | ```swift 107 | Queue.Background.after(2) { 108 | // Do some stuff on Background after 2 seconds 109 | } 110 | ``` 111 | 112 | ### Iterate on a Queue 113 | 114 | ```swift 115 | Queue.Background.iterate(4) { i in 116 | // Do some stuff on Background 4 times 117 | } 118 | ``` 119 | 120 | ### Current Queue 121 | 122 | ```swift 123 | Queue.current // Get current queue 124 | Queue.Background.isCurrent // Check if background is current queue 125 | ``` 126 | Take notice that will work only on **Custom Queues** created with the designed initializer `Queue(name:String, kind:Queue.Custom.Kind)`, the **Main queue** and **Global queues**. 127 | 128 | ## Task 129 | A task represents a block to be dispatched on a queue. 130 | 131 | ```swift 132 | let t = Task(queue:.Utility) { 133 | ... 134 | } 135 | // Or 136 | let t = Queue.Utility + { 137 | ... 138 | } 139 | 140 | t.async() // Dispatch asynchronously 141 | 142 | group.async(t) // Dispatch on a group 143 | 144 | let tasks:[Task] = ... 145 | g.async(tasks) // Tasks dispatched on a group. 146 | ``` 147 | A task can be chained with a `block` or an another `Task` 148 | 149 | ```swift 150 | t.chain { 151 | // Executed after t on same queue 152 | }.chain(Task(queue:.Main) { 153 | // Executed after previous block on the main queue 154 | }) 155 | t.async() 156 | 157 | // Or chain directly after async and use the operator shortcut 158 | t.async() <> { 159 | // Executed after t on same queue 160 | } <> Queue.Main + { 161 | // Executed after previous block on the main queue 162 | } 163 | ``` 164 | 165 | ## Group 166 | A group allows to associate multiple blocks to be dispatched asynchronously. 167 | 168 | ```swift 169 | let g = Group(queue:.Utility) // By default the group queue is Background 170 | 171 | g.async { 172 | // Block dispatched on the group's queue. 173 | } <<< { 174 | // Block dispatched on the group's queue using the operator. 175 | } <<< Task(queue:.Main) { 176 | // Block dispatched on the Main queue (see Task). 177 | } 178 | 179 | let blocks:[()-> Void] = ... 180 | g.async(blocks) // Blocks dispatched on the group's queue. 181 | ``` 182 | There is two ways to track group's blocks execution: 183 | ```swift 184 | g.notify { 185 | // Block executed on the group queue when blocks previously dispatched on the group have been executed. 186 | } 187 | g.notify(Queue.Main + { 188 | // Block executed on the Main queue when blocks previously dispatched on the group have been executed. 189 | }) 190 | 191 | g.wait() // Wait on the current process the group's blocks execution. 192 | ``` 193 | 194 | ## Once 195 | Execute a block once and only once. 196 | 197 | ```swift 198 | let once = OnceDispatcher() // Store it somewhere 199 | ... 200 | once { 201 | // Executed only one time 202 | } 203 | ``` 204 | 205 | ## Timer 206 | 207 | A timer allows to schedule a block on a specified queue with an interval or a date. 208 | ```swift 209 | let timer = Timer.scheduleWithInterval(2, onQueue: .Background) { 210 | // Do some stuff on Background after 2 seconds 211 | } 212 | // Equivalent to: 213 | let timer = Timer(queue: .Background, interval: 2) 214 | timer.handler { 215 | // Do some stuff on Background after 2 seconds 216 | } 217 | timer.start() // Timers are paused at Initialization 218 | ``` 219 | A timer can be paused or stopped. 220 | ```swift 221 | timer.pause() 222 | timer.start() 223 | timer.stop() 224 | ``` 225 | A timer can be repeated, use a date... 226 | ```swift 227 | let date: NSDate = ... 228 | let timer = Timer(queue: .Background, date: date) 229 | timer.repeatInterval = 4 230 | timer.tolerance = 1 // Add some tolerance 231 | timer.handler { 232 | // Do some stuff on Background on specified date and after every 4 seconds approximately 233 | } 234 | timer.start() 235 | ``` 236 | 237 | ## Semaphore 238 | There is three kinds of semaphore: 239 | 240 | | Kind | Initial Resource(s) | 241 | | :------------------------------ | :--------------------- | 242 | | Binary | 1 | 243 | | Barrier | 0 | 244 | | Counting(resource:UInt16) | custom | 245 | 246 | Initialize a semaphore: 247 | 248 | ```swift 249 | let sem = Semaphore(.Binary) 250 | let customSem = Semaphore(resource:5) 251 | 252 | ``` 253 | 254 | You can decrement/increment semaphore's resource by using `wait/signal` methods: 255 | 256 | ```swift 257 | sem.wait() 258 | // Do some stuff when a resource is available 259 | sem.signal() 260 | 261 | // Or 262 | sem-- 263 | ... 264 | sem++ 265 | ``` 266 | Or by using the `perform` convenient method with a closure: 267 | 268 | ```swift 269 | sem.perform { 270 | // Do some stuff when a resource is available 271 | } 272 | 273 | // Or 274 | sem <<< { 275 | ... 276 | } 277 | ``` 278 | 279 | ### Mutex 280 | A **mutex** is essentially the same thing as a **binary semaphore** except that only the block that locked the resource is supposed to unlock it. 281 | 282 | ```swift 283 | let m = Mutex() 284 | ... 285 | m.sync { 286 | // Do some stuff when a mutext is available 287 | } 288 | 289 | // Or 290 | m <<< { 291 | ... 292 | } 293 | ``` 294 | 295 | ### LockedObject 296 | `LockedObject` is convenient class to lock access to an object with an internal **mutext**. 297 | 298 | ```swift 299 | let myobj = MyObject() 300 | let l = LockedObject(myobj) 301 | ... 302 | l.access { obj in 303 | // Only one process at a time will access the locked object 304 | } 305 | 306 | // Or 307 | l <<< { obj in 308 | ... 309 | } 310 | ``` 311 | 312 | 313 | 314 | ## Use with [cocoapods](http://cocoapods.org/) 315 | 316 | Add `pod 'Eki'` to your `Podfile` and run `pod install`. 317 | -------------------------------------------------------------------------------- /Eki-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3F2E56F119EEB33400B2E1F5 /* Eki.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F2E56F019EEB33400B2E1F5 /* Eki.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 3F2E56F719EEB33400B2E1F5 /* Eki.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */; }; 12 | 3F2E56FE19EEB33400B2E1F5 /* EkiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */; }; 13 | 3F2E570819EEB38000B2E1F5 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F2E570719EEB38000B2E1F5 /* Queue.swift */; }; 14 | 3F350CB21B04EE2A00465643 /* Semaphore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F350CB11B04EE2A00465643 /* Semaphore.swift */; }; 15 | 3F77724319F57A7900BCABF9 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724219F57A7900BCABF9 /* Group.swift */; }; 16 | 3F77724519F57A8900BCABF9 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724419F57A8900BCABF9 /* Task.swift */; }; 17 | 3F77724719F57ADA00BCABF9 /* Once.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724619F57ADA00BCABF9 /* Once.swift */; }; 18 | C484B1E11BB976F600E264A8 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C484B1E01BB976F600E264A8 /* Timer.swift */; settings = {ASSET_TAGS = (); }; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 3F2E56F819EEB33400B2E1F5 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 3F2E56E219EEB33400B2E1F5 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 3F2E56EA19EEB33400B2E1F5; 27 | remoteInfo = Eki; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eki.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 3F2E56EF19EEB33400B2E1F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 3F2E56F019EEB33400B2E1F5 /* Eki.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Eki.h; sourceTree = ""; }; 35 | 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EkiTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 3F2E56FC19EEB33400B2E1F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EkiTests.swift; sourceTree = ""; }; 38 | 3F2E570719EEB38000B2E1F5 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; 39 | 3F350CB11B04EE2A00465643 /* Semaphore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Semaphore.swift; sourceTree = ""; }; 40 | 3F77724219F57A7900BCABF9 /* Group.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = ""; }; 41 | 3F77724419F57A8900BCABF9 /* Task.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; 42 | 3F77724619F57ADA00BCABF9 /* Once.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Once.swift; sourceTree = ""; }; 43 | C484B1E01BB976F600E264A8 /* Timer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 3F2E56E719EEB33400B2E1F5 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | 3F2E56F319EEB33400B2E1F5 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | 3F2E56F719EEB33400B2E1F5 /* Eki.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 3F2E56E119EEB33400B2E1F5 = { 66 | isa = PBXGroup; 67 | children = ( 68 | 3F2E56ED19EEB33400B2E1F5 /* Eki */, 69 | 3F2E56FA19EEB33400B2E1F5 /* EkiTests */, 70 | 3F2E56EC19EEB33400B2E1F5 /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 3F2E56EC19EEB33400B2E1F5 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */, 78 | 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 3F2E56ED19EEB33400B2E1F5 /* Eki */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 3F2E570719EEB38000B2E1F5 /* Queue.swift */, 87 | 3F77724219F57A7900BCABF9 /* Group.swift */, 88 | 3F77724419F57A8900BCABF9 /* Task.swift */, 89 | 3F77724619F57ADA00BCABF9 /* Once.swift */, 90 | 3F350CB11B04EE2A00465643 /* Semaphore.swift */, 91 | C484B1E01BB976F600E264A8 /* Timer.swift */, 92 | 3F2E56F019EEB33400B2E1F5 /* Eki.h */, 93 | 3F2E56EE19EEB33400B2E1F5 /* Supporting Files */, 94 | ); 95 | path = Eki; 96 | sourceTree = ""; 97 | }; 98 | 3F2E56EE19EEB33400B2E1F5 /* Supporting Files */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 3F2E56EF19EEB33400B2E1F5 /* Info.plist */, 102 | ); 103 | name = "Supporting Files"; 104 | sourceTree = ""; 105 | }; 106 | 3F2E56FA19EEB33400B2E1F5 /* EkiTests */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */, 110 | 3F2E56FB19EEB33400B2E1F5 /* Supporting Files */, 111 | ); 112 | path = EkiTests; 113 | sourceTree = ""; 114 | }; 115 | 3F2E56FB19EEB33400B2E1F5 /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 3F2E56FC19EEB33400B2E1F5 /* Info.plist */, 119 | ); 120 | name = "Supporting Files"; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXHeadersBuildPhase section */ 126 | 3F2E56E819EEB33400B2E1F5 /* Headers */ = { 127 | isa = PBXHeadersBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 3F2E56F119EEB33400B2E1F5 /* Eki.h in Headers */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXHeadersBuildPhase section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | 3F2E56EA19EEB33400B2E1F5 /* Eki */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = 3F2E570119EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "Eki" */; 140 | buildPhases = ( 141 | 3F2E56E619EEB33400B2E1F5 /* Sources */, 142 | 3F2E56E719EEB33400B2E1F5 /* Frameworks */, 143 | 3F2E56E819EEB33400B2E1F5 /* Headers */, 144 | 3F2E56E919EEB33400B2E1F5 /* Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = Eki; 151 | productName = Eki; 152 | productReference = 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */; 153 | productType = "com.apple.product-type.framework"; 154 | }; 155 | 3F2E56F519EEB33400B2E1F5 /* EkiTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 3F2E570419EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "EkiTests" */; 158 | buildPhases = ( 159 | 3F2E56F219EEB33400B2E1F5 /* Sources */, 160 | 3F2E56F319EEB33400B2E1F5 /* Frameworks */, 161 | 3F2E56F419EEB33400B2E1F5 /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | 3F2E56F919EEB33400B2E1F5 /* PBXTargetDependency */, 167 | ); 168 | name = EkiTests; 169 | productName = EkiTests; 170 | productReference = 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */; 171 | productType = "com.apple.product-type.bundle.unit-test"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | 3F2E56E219EEB33400B2E1F5 /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastSwiftUpdateCheck = 0700; 180 | LastUpgradeCheck = 0610; 181 | ORGANIZATIONNAME = "Jérémy Marchand"; 182 | TargetAttributes = { 183 | 3F2E56EA19EEB33400B2E1F5 = { 184 | CreatedOnToolsVersion = 6.1; 185 | }; 186 | 3F2E56F519EEB33400B2E1F5 = { 187 | CreatedOnToolsVersion = 6.1; 188 | }; 189 | }; 190 | }; 191 | buildConfigurationList = 3F2E56E519EEB33400B2E1F5 /* Build configuration list for PBXProject "Eki-iOS" */; 192 | compatibilityVersion = "Xcode 3.2"; 193 | developmentRegion = English; 194 | hasScannedForEncodings = 0; 195 | knownRegions = ( 196 | en, 197 | ); 198 | mainGroup = 3F2E56E119EEB33400B2E1F5; 199 | productRefGroup = 3F2E56EC19EEB33400B2E1F5 /* Products */; 200 | projectDirPath = ""; 201 | projectRoot = ""; 202 | targets = ( 203 | 3F2E56EA19EEB33400B2E1F5 /* Eki */, 204 | 3F2E56F519EEB33400B2E1F5 /* EkiTests */, 205 | ); 206 | }; 207 | /* End PBXProject section */ 208 | 209 | /* Begin PBXResourcesBuildPhase section */ 210 | 3F2E56E919EEB33400B2E1F5 /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | 3F2E56F419EEB33400B2E1F5 /* Resources */ = { 218 | isa = PBXResourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXResourcesBuildPhase section */ 225 | 226 | /* Begin PBXSourcesBuildPhase section */ 227 | 3F2E56E619EEB33400B2E1F5 /* Sources */ = { 228 | isa = PBXSourcesBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | 3F2E570819EEB38000B2E1F5 /* Queue.swift in Sources */, 232 | 3F77724319F57A7900BCABF9 /* Group.swift in Sources */, 233 | 3F350CB21B04EE2A00465643 /* Semaphore.swift in Sources */, 234 | C484B1E11BB976F600E264A8 /* Timer.swift in Sources */, 235 | 3F77724719F57ADA00BCABF9 /* Once.swift in Sources */, 236 | 3F77724519F57A8900BCABF9 /* Task.swift in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | 3F2E56F219EEB33400B2E1F5 /* Sources */ = { 241 | isa = PBXSourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 3F2E56FE19EEB33400B2E1F5 /* EkiTests.swift in Sources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXSourcesBuildPhase section */ 249 | 250 | /* Begin PBXTargetDependency section */ 251 | 3F2E56F919EEB33400B2E1F5 /* PBXTargetDependency */ = { 252 | isa = PBXTargetDependency; 253 | target = 3F2E56EA19EEB33400B2E1F5 /* Eki */; 254 | targetProxy = 3F2E56F819EEB33400B2E1F5 /* PBXContainerItemProxy */; 255 | }; 256 | /* End PBXTargetDependency section */ 257 | 258 | /* Begin XCBuildConfiguration section */ 259 | 3F2E56FF19EEB33400B2E1F5 /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | ALWAYS_SEARCH_USER_PATHS = NO; 263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 264 | CLANG_CXX_LIBRARY = "libc++"; 265 | CLANG_ENABLE_MODULES = YES; 266 | CLANG_ENABLE_OBJC_ARC = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_CONSTANT_CONVERSION = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INT_CONVERSION = YES; 273 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | COPY_PHASE_STRIP = NO; 277 | CURRENT_PROJECT_VERSION = 1; 278 | ENABLE_STRICT_OBJC_MSGSEND = YES; 279 | GCC_C_LANGUAGE_STANDARD = gnu99; 280 | GCC_DYNAMIC_NO_PIC = NO; 281 | GCC_OPTIMIZATION_LEVEL = 0; 282 | GCC_PREPROCESSOR_DEFINITIONS = ( 283 | "DEBUG=1", 284 | "$(inherited)", 285 | ); 286 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 287 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 288 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 289 | GCC_WARN_UNDECLARED_SELECTOR = YES; 290 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 291 | GCC_WARN_UNUSED_FUNCTION = YES; 292 | GCC_WARN_UNUSED_VARIABLE = YES; 293 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 294 | MTL_ENABLE_DEBUG_INFO = YES; 295 | ONLY_ACTIVE_ARCH = YES; 296 | SDKROOT = iphoneos; 297 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 298 | VERSIONING_SYSTEM = "apple-generic"; 299 | VERSION_INFO_PREFIX = ""; 300 | }; 301 | name = Debug; 302 | }; 303 | 3F2E570019EEB33400B2E1F5 /* Release */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ALWAYS_SEARCH_USER_PATHS = NO; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_EMPTY_BODY = YES; 315 | CLANG_WARN_ENUM_CONVERSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | COPY_PHASE_STRIP = YES; 321 | CURRENT_PROJECT_VERSION = 1; 322 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 323 | ENABLE_NS_ASSERTIONS = NO; 324 | ENABLE_STRICT_OBJC_MSGSEND = YES; 325 | GCC_C_LANGUAGE_STANDARD = gnu99; 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 333 | MTL_ENABLE_DEBUG_INFO = NO; 334 | SDKROOT = iphoneos; 335 | VERSIONING_SYSTEM = "apple-generic"; 336 | VERSION_INFO_PREFIX = ""; 337 | }; 338 | name = Release; 339 | }; 340 | 3F2E570219EEB33400B2E1F5 /* Debug */ = { 341 | isa = XCBuildConfiguration; 342 | buildSettings = { 343 | COMBINE_HIDPI_IMAGES = YES; 344 | DEFINES_MODULE = YES; 345 | DYLIB_COMPATIBILITY_VERSION = 1; 346 | DYLIB_CURRENT_VERSION = 1; 347 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 348 | FRAMEWORK_VERSION = A; 349 | INFOPLIST_FILE = Eki/Info.plist; 350 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | SKIP_INSTALL = YES; 354 | }; 355 | name = Debug; 356 | }; 357 | 3F2E570319EEB33400B2E1F5 /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | COMBINE_HIDPI_IMAGES = YES; 361 | DEFINES_MODULE = YES; 362 | DYLIB_COMPATIBILITY_VERSION = 1; 363 | DYLIB_CURRENT_VERSION = 1; 364 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 365 | FRAMEWORK_VERSION = A; 366 | INFOPLIST_FILE = Eki/Info.plist; 367 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | SKIP_INSTALL = YES; 371 | }; 372 | name = Release; 373 | }; 374 | 3F2E570519EEB33400B2E1F5 /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | COMBINE_HIDPI_IMAGES = YES; 378 | FRAMEWORK_SEARCH_PATHS = ( 379 | "$(DEVELOPER_FRAMEWORKS_DIR)", 380 | "$(inherited)", 381 | ); 382 | GCC_PREPROCESSOR_DEFINITIONS = ( 383 | "DEBUG=1", 384 | "$(inherited)", 385 | ); 386 | INFOPLIST_FILE = EkiTests/Info.plist; 387 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | }; 390 | name = Debug; 391 | }; 392 | 3F2E570619EEB33400B2E1F5 /* Release */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | COMBINE_HIDPI_IMAGES = YES; 396 | FRAMEWORK_SEARCH_PATHS = ( 397 | "$(DEVELOPER_FRAMEWORKS_DIR)", 398 | "$(inherited)", 399 | ); 400 | INFOPLIST_FILE = EkiTests/Info.plist; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 402 | PRODUCT_NAME = "$(TARGET_NAME)"; 403 | }; 404 | name = Release; 405 | }; 406 | /* End XCBuildConfiguration section */ 407 | 408 | /* Begin XCConfigurationList section */ 409 | 3F2E56E519EEB33400B2E1F5 /* Build configuration list for PBXProject "Eki-iOS" */ = { 410 | isa = XCConfigurationList; 411 | buildConfigurations = ( 412 | 3F2E56FF19EEB33400B2E1F5 /* Debug */, 413 | 3F2E570019EEB33400B2E1F5 /* Release */, 414 | ); 415 | defaultConfigurationIsVisible = 0; 416 | defaultConfigurationName = Release; 417 | }; 418 | 3F2E570119EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "Eki" */ = { 419 | isa = XCConfigurationList; 420 | buildConfigurations = ( 421 | 3F2E570219EEB33400B2E1F5 /* Debug */, 422 | 3F2E570319EEB33400B2E1F5 /* Release */, 423 | ); 424 | defaultConfigurationIsVisible = 0; 425 | defaultConfigurationName = Release; 426 | }; 427 | 3F2E570419EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "EkiTests" */ = { 428 | isa = XCConfigurationList; 429 | buildConfigurations = ( 430 | 3F2E570519EEB33400B2E1F5 /* Debug */, 431 | 3F2E570619EEB33400B2E1F5 /* Release */, 432 | ); 433 | defaultConfigurationIsVisible = 0; 434 | defaultConfigurationName = Release; 435 | }; 436 | /* End XCConfigurationList section */ 437 | }; 438 | rootObject = 3F2E56E219EEB33400B2E1F5 /* Project object */; 439 | } 440 | -------------------------------------------------------------------------------- /Eki-OSX.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3F2E56F119EEB33400B2E1F5 /* Eki.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F2E56F019EEB33400B2E1F5 /* Eki.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 3F2E56F719EEB33400B2E1F5 /* Eki.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */; }; 12 | 3F2E56FE19EEB33400B2E1F5 /* EkiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */; }; 13 | 3F2E570819EEB38000B2E1F5 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F2E570719EEB38000B2E1F5 /* Queue.swift */; }; 14 | 3F350CB21B04EE2A00465643 /* Semaphore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F350CB11B04EE2A00465643 /* Semaphore.swift */; }; 15 | 3F77724319F57A7900BCABF9 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724219F57A7900BCABF9 /* Group.swift */; }; 16 | 3F77724519F57A8900BCABF9 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724419F57A8900BCABF9 /* Task.swift */; }; 17 | 3F77724719F57ADA00BCABF9 /* Once.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F77724619F57ADA00BCABF9 /* Once.swift */; }; 18 | C484B1E31BB984A900E264A8 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C484B1E21BB984A900E264A8 /* Timer.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 3F2E56F819EEB33400B2E1F5 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 3F2E56E219EEB33400B2E1F5 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 3F2E56EA19EEB33400B2E1F5; 27 | remoteInfo = Eki; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eki.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 3F2E56EF19EEB33400B2E1F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 3F2E56F019EEB33400B2E1F5 /* Eki.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Eki.h; sourceTree = ""; }; 35 | 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EkiTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 3F2E56FC19EEB33400B2E1F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EkiTests.swift; sourceTree = ""; }; 38 | 3F2E570719EEB38000B2E1F5 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; 39 | 3F350CB11B04EE2A00465643 /* Semaphore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Semaphore.swift; sourceTree = ""; }; 40 | 3F77724219F57A7900BCABF9 /* Group.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = ""; }; 41 | 3F77724419F57A8900BCABF9 /* Task.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; 42 | 3F77724619F57ADA00BCABF9 /* Once.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Once.swift; sourceTree = ""; }; 43 | C484B1E21BB984A900E264A8 /* Timer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 3F2E56E719EEB33400B2E1F5 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | 3F2E56F319EEB33400B2E1F5 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | 3F2E56F719EEB33400B2E1F5 /* Eki.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 3F2E56E119EEB33400B2E1F5 = { 66 | isa = PBXGroup; 67 | children = ( 68 | 3F2E56ED19EEB33400B2E1F5 /* Eki */, 69 | 3F2E56FA19EEB33400B2E1F5 /* EkiTests */, 70 | 3F2E56EC19EEB33400B2E1F5 /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 3F2E56EC19EEB33400B2E1F5 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */, 78 | 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 3F2E56ED19EEB33400B2E1F5 /* Eki */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 3F2E570719EEB38000B2E1F5 /* Queue.swift */, 87 | 3F77724219F57A7900BCABF9 /* Group.swift */, 88 | 3F77724419F57A8900BCABF9 /* Task.swift */, 89 | 3F77724619F57ADA00BCABF9 /* Once.swift */, 90 | 3F350CB11B04EE2A00465643 /* Semaphore.swift */, 91 | C484B1E21BB984A900E264A8 /* Timer.swift */, 92 | 3F2E56F019EEB33400B2E1F5 /* Eki.h */, 93 | 3F2E56EE19EEB33400B2E1F5 /* Supporting Files */, 94 | ); 95 | path = Eki; 96 | sourceTree = ""; 97 | }; 98 | 3F2E56EE19EEB33400B2E1F5 /* Supporting Files */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 3F2E56EF19EEB33400B2E1F5 /* Info.plist */, 102 | ); 103 | name = "Supporting Files"; 104 | sourceTree = ""; 105 | }; 106 | 3F2E56FA19EEB33400B2E1F5 /* EkiTests */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 3F2E56FD19EEB33400B2E1F5 /* EkiTests.swift */, 110 | 3F2E56FB19EEB33400B2E1F5 /* Supporting Files */, 111 | ); 112 | path = EkiTests; 113 | sourceTree = ""; 114 | }; 115 | 3F2E56FB19EEB33400B2E1F5 /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 3F2E56FC19EEB33400B2E1F5 /* Info.plist */, 119 | ); 120 | name = "Supporting Files"; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXHeadersBuildPhase section */ 126 | 3F2E56E819EEB33400B2E1F5 /* Headers */ = { 127 | isa = PBXHeadersBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 3F2E56F119EEB33400B2E1F5 /* Eki.h in Headers */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXHeadersBuildPhase section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | 3F2E56EA19EEB33400B2E1F5 /* Eki */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = 3F2E570119EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "Eki" */; 140 | buildPhases = ( 141 | 3F406DA21C5D6BDB0066FBED /* Swift Lint */, 142 | 3F2E56E619EEB33400B2E1F5 /* Sources */, 143 | 3F2E56E719EEB33400B2E1F5 /* Frameworks */, 144 | 3F2E56E819EEB33400B2E1F5 /* Headers */, 145 | 3F2E56E919EEB33400B2E1F5 /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | ); 151 | name = Eki; 152 | productName = Eki; 153 | productReference = 3F2E56EB19EEB33400B2E1F5 /* Eki.framework */; 154 | productType = "com.apple.product-type.framework"; 155 | }; 156 | 3F2E56F519EEB33400B2E1F5 /* EkiTests */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = 3F2E570419EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "EkiTests" */; 159 | buildPhases = ( 160 | 3F2E56F219EEB33400B2E1F5 /* Sources */, 161 | 3F2E56F319EEB33400B2E1F5 /* Frameworks */, 162 | 3F2E56F419EEB33400B2E1F5 /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | 3F2E56F919EEB33400B2E1F5 /* PBXTargetDependency */, 168 | ); 169 | name = EkiTests; 170 | productName = EkiTests; 171 | productReference = 3F2E56F619EEB33400B2E1F5 /* EkiTests.xctest */; 172 | productType = "com.apple.product-type.bundle.unit-test"; 173 | }; 174 | /* End PBXNativeTarget section */ 175 | 176 | /* Begin PBXProject section */ 177 | 3F2E56E219EEB33400B2E1F5 /* Project object */ = { 178 | isa = PBXProject; 179 | attributes = { 180 | LastSwiftUpdateCheck = 0700; 181 | LastUpgradeCheck = 0700; 182 | ORGANIZATIONNAME = "Jérémy Marchand"; 183 | TargetAttributes = { 184 | 3F2E56EA19EEB33400B2E1F5 = { 185 | CreatedOnToolsVersion = 6.1; 186 | }; 187 | 3F2E56F519EEB33400B2E1F5 = { 188 | CreatedOnToolsVersion = 6.1; 189 | }; 190 | }; 191 | }; 192 | buildConfigurationList = 3F2E56E519EEB33400B2E1F5 /* Build configuration list for PBXProject "Eki-OSX" */; 193 | compatibilityVersion = "Xcode 3.2"; 194 | developmentRegion = English; 195 | hasScannedForEncodings = 0; 196 | knownRegions = ( 197 | en, 198 | ); 199 | mainGroup = 3F2E56E119EEB33400B2E1F5; 200 | productRefGroup = 3F2E56EC19EEB33400B2E1F5 /* Products */; 201 | projectDirPath = ""; 202 | projectRoot = ""; 203 | targets = ( 204 | 3F2E56EA19EEB33400B2E1F5 /* Eki */, 205 | 3F2E56F519EEB33400B2E1F5 /* EkiTests */, 206 | ); 207 | }; 208 | /* End PBXProject section */ 209 | 210 | /* Begin PBXResourcesBuildPhase section */ 211 | 3F2E56E919EEB33400B2E1F5 /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | 3F2E56F419EEB33400B2E1F5 /* Resources */ = { 219 | isa = PBXResourcesBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | /* End PBXResourcesBuildPhase section */ 226 | 227 | /* Begin PBXShellScriptBuildPhase section */ 228 | 3F406DA21C5D6BDB0066FBED /* Swift Lint */ = { 229 | isa = PBXShellScriptBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | ); 233 | inputPaths = ( 234 | ); 235 | name = "Swift Lint"; 236 | outputPaths = ( 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | shellPath = /bin/sh; 240 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint autocorrect\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; 241 | }; 242 | /* End PBXShellScriptBuildPhase section */ 243 | 244 | /* Begin PBXSourcesBuildPhase section */ 245 | 3F2E56E619EEB33400B2E1F5 /* Sources */ = { 246 | isa = PBXSourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | 3F2E570819EEB38000B2E1F5 /* Queue.swift in Sources */, 250 | 3F77724319F57A7900BCABF9 /* Group.swift in Sources */, 251 | 3F350CB21B04EE2A00465643 /* Semaphore.swift in Sources */, 252 | C484B1E31BB984A900E264A8 /* Timer.swift in Sources */, 253 | 3F77724719F57ADA00BCABF9 /* Once.swift in Sources */, 254 | 3F77724519F57A8900BCABF9 /* Task.swift in Sources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | 3F2E56F219EEB33400B2E1F5 /* Sources */ = { 259 | isa = PBXSourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 3F2E56FE19EEB33400B2E1F5 /* EkiTests.swift in Sources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXSourcesBuildPhase section */ 267 | 268 | /* Begin PBXTargetDependency section */ 269 | 3F2E56F919EEB33400B2E1F5 /* PBXTargetDependency */ = { 270 | isa = PBXTargetDependency; 271 | target = 3F2E56EA19EEB33400B2E1F5 /* Eki */; 272 | targetProxy = 3F2E56F819EEB33400B2E1F5 /* PBXContainerItemProxy */; 273 | }; 274 | /* End PBXTargetDependency section */ 275 | 276 | /* Begin XCBuildConfiguration section */ 277 | 3F2E56FF19EEB33400B2E1F5 /* Debug */ = { 278 | isa = XCBuildConfiguration; 279 | buildSettings = { 280 | ALWAYS_SEARCH_USER_PATHS = NO; 281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 282 | CLANG_CXX_LIBRARY = "libc++"; 283 | CLANG_ENABLE_MODULES = YES; 284 | CLANG_ENABLE_OBJC_ARC = YES; 285 | CLANG_WARN_BOOL_CONVERSION = YES; 286 | CLANG_WARN_CONSTANT_CONVERSION = YES; 287 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 288 | CLANG_WARN_EMPTY_BODY = YES; 289 | CLANG_WARN_ENUM_CONVERSION = YES; 290 | CLANG_WARN_INT_CONVERSION = YES; 291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 292 | CLANG_WARN_UNREACHABLE_CODE = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | COPY_PHASE_STRIP = NO; 295 | CURRENT_PROJECT_VERSION = 1; 296 | ENABLE_STRICT_OBJC_MSGSEND = YES; 297 | ENABLE_TESTABILITY = YES; 298 | GCC_C_LANGUAGE_STANDARD = gnu99; 299 | GCC_DYNAMIC_NO_PIC = NO; 300 | GCC_OPTIMIZATION_LEVEL = 0; 301 | GCC_PREPROCESSOR_DEFINITIONS = ( 302 | "DEBUG=1", 303 | "$(inherited)", 304 | ); 305 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 308 | GCC_WARN_UNDECLARED_SELECTOR = YES; 309 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 310 | GCC_WARN_UNUSED_FUNCTION = YES; 311 | GCC_WARN_UNUSED_VARIABLE = YES; 312 | MACOSX_DEPLOYMENT_TARGET = 10.10; 313 | MTL_ENABLE_DEBUG_INFO = YES; 314 | ONLY_ACTIVE_ARCH = YES; 315 | SDKROOT = macosx; 316 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 317 | VERSIONING_SYSTEM = "apple-generic"; 318 | VERSION_INFO_PREFIX = ""; 319 | }; 320 | name = Debug; 321 | }; 322 | 3F2E570019EEB33400B2E1F5 /* Release */ = { 323 | isa = XCBuildConfiguration; 324 | buildSettings = { 325 | ALWAYS_SEARCH_USER_PATHS = NO; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_MODULES = YES; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_CONSTANT_CONVERSION = YES; 332 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 333 | CLANG_WARN_EMPTY_BODY = YES; 334 | CLANG_WARN_ENUM_CONVERSION = YES; 335 | CLANG_WARN_INT_CONVERSION = YES; 336 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 337 | CLANG_WARN_UNREACHABLE_CODE = YES; 338 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 339 | COPY_PHASE_STRIP = YES; 340 | CURRENT_PROJECT_VERSION = 1; 341 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 342 | ENABLE_NS_ASSERTIONS = NO; 343 | ENABLE_STRICT_OBJC_MSGSEND = YES; 344 | GCC_C_LANGUAGE_STANDARD = gnu99; 345 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 346 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 347 | GCC_WARN_UNDECLARED_SELECTOR = YES; 348 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 349 | GCC_WARN_UNUSED_FUNCTION = YES; 350 | GCC_WARN_UNUSED_VARIABLE = YES; 351 | MACOSX_DEPLOYMENT_TARGET = 10.10; 352 | MTL_ENABLE_DEBUG_INFO = NO; 353 | SDKROOT = macosx; 354 | VERSIONING_SYSTEM = "apple-generic"; 355 | VERSION_INFO_PREFIX = ""; 356 | }; 357 | name = Release; 358 | }; 359 | 3F2E570219EEB33400B2E1F5 /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | COMBINE_HIDPI_IMAGES = YES; 363 | DEFINES_MODULE = YES; 364 | DYLIB_COMPATIBILITY_VERSION = 1; 365 | DYLIB_CURRENT_VERSION = 1; 366 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 367 | FRAMEWORK_VERSION = A; 368 | INFOPLIST_FILE = Eki/Info.plist; 369 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 370 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 371 | PRODUCT_BUNDLE_IDENTIFIER = "com.kodlian.$(PRODUCT_NAME:rfc1034identifier)"; 372 | PRODUCT_NAME = "$(TARGET_NAME)"; 373 | SKIP_INSTALL = YES; 374 | }; 375 | name = Debug; 376 | }; 377 | 3F2E570319EEB33400B2E1F5 /* Release */ = { 378 | isa = XCBuildConfiguration; 379 | buildSettings = { 380 | COMBINE_HIDPI_IMAGES = YES; 381 | DEFINES_MODULE = YES; 382 | DYLIB_COMPATIBILITY_VERSION = 1; 383 | DYLIB_CURRENT_VERSION = 1; 384 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 385 | FRAMEWORK_VERSION = A; 386 | INFOPLIST_FILE = Eki/Info.plist; 387 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 389 | PRODUCT_BUNDLE_IDENTIFIER = "com.kodlian.$(PRODUCT_NAME:rfc1034identifier)"; 390 | PRODUCT_NAME = "$(TARGET_NAME)"; 391 | SKIP_INSTALL = YES; 392 | }; 393 | name = Release; 394 | }; 395 | 3F2E570519EEB33400B2E1F5 /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | COMBINE_HIDPI_IMAGES = YES; 399 | FRAMEWORK_SEARCH_PATHS = ( 400 | "$(DEVELOPER_FRAMEWORKS_DIR)", 401 | "$(inherited)", 402 | ); 403 | GCC_PREPROCESSOR_DEFINITIONS = ( 404 | "DEBUG=1", 405 | "$(inherited)", 406 | ); 407 | INFOPLIST_FILE = EkiTests/Info.plist; 408 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 409 | PRODUCT_BUNDLE_IDENTIFIER = "com.kodlian.$(PRODUCT_NAME:rfc1034identifier)"; 410 | PRODUCT_NAME = "$(TARGET_NAME)"; 411 | }; 412 | name = Debug; 413 | }; 414 | 3F2E570619EEB33400B2E1F5 /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | COMBINE_HIDPI_IMAGES = YES; 418 | FRAMEWORK_SEARCH_PATHS = ( 419 | "$(DEVELOPER_FRAMEWORKS_DIR)", 420 | "$(inherited)", 421 | ); 422 | INFOPLIST_FILE = EkiTests/Info.plist; 423 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 424 | PRODUCT_BUNDLE_IDENTIFIER = "com.kodlian.$(PRODUCT_NAME:rfc1034identifier)"; 425 | PRODUCT_NAME = "$(TARGET_NAME)"; 426 | }; 427 | name = Release; 428 | }; 429 | /* End XCBuildConfiguration section */ 430 | 431 | /* Begin XCConfigurationList section */ 432 | 3F2E56E519EEB33400B2E1F5 /* Build configuration list for PBXProject "Eki-OSX" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | 3F2E56FF19EEB33400B2E1F5 /* Debug */, 436 | 3F2E570019EEB33400B2E1F5 /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | 3F2E570119EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "Eki" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | 3F2E570219EEB33400B2E1F5 /* Debug */, 445 | 3F2E570319EEB33400B2E1F5 /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | 3F2E570419EEB33400B2E1F5 /* Build configuration list for PBXNativeTarget "EkiTests" */ = { 451 | isa = XCConfigurationList; 452 | buildConfigurations = ( 453 | 3F2E570519EEB33400B2E1F5 /* Debug */, 454 | 3F2E570619EEB33400B2E1F5 /* Release */, 455 | ); 456 | defaultConfigurationIsVisible = 0; 457 | defaultConfigurationName = Release; 458 | }; 459 | /* End XCConfigurationList section */ 460 | }; 461 | rootObject = 3F2E56E219EEB33400B2E1F5 /* Project object */; 462 | } 463 | --------------------------------------------------------------------------------