diff --git a/Kommander/CurrentDispatcher.swift b/Kommander/CurrentDispatcher.swift index c0e238b..1059e92 100644 --- a/Kommander/CurrentDispatcher.swift +++ b/Kommander/CurrentDispatcher.swift @@ -8,11 +8,11 @@ import Foundation -open class CurrentDispatcher: MainDispatcher { +public class CurrentDispatcher: MainDispatcher { public override init() { super.init() - if let currentOperationQueue = OperationQueue.current { + if let currentOperationQueue = NSOperationQueue.currentQueue() { operationQueue = currentOperationQueue if let underlyingQueue = currentOperationQueue.underlyingQueue { dispatchQueue = underlyingQueue diff --git a/Kommander/Dispatcher.swift b/Kommander/Dispatcher.swift index eaf733c..9f0677c 100644 --- a/Kommander/Dispatcher.swift +++ b/Kommander/Dispatcher.swift @@ -12,76 +12,59 @@ private enum Priority { case operation, dispatch } -open class Dispatcher { +public class Dispatcher { - internal final var operationQueue = OperationQueue() - internal final var dispatchQueue = DispatchQueue(label: UUID().uuidString) + internal final var operationQueue = NSOperationQueue() + internal final var dispatchQueue = dispatch_queue_create(NSUUID().UUIDString, DISPATCH_QUEUE_SERIAL) private final var priority = Priority.operation public convenience init() { - self.init(name: nil, qos: nil, maxConcurrentOperationCount: OperationQueue.defaultMaxConcurrentOperationCount) + self.init(name: nil, qos: nil, maxConcurrentOperationCount: NSOperationQueueDefaultMaxConcurrentOperationCount) } - public init(name: String?, qos: QualityOfService?, maxConcurrentOperationCount: Int) { - operationQueue.name = name ?? UUID().uuidString - operationQueue.qualityOfService = qos ?? .default + public init(name: String?, qos: NSQualityOfService?, maxConcurrentOperationCount: Int) { + operationQueue.name = name ?? NSUUID().UUIDString + operationQueue.qualityOfService = qos ?? .Default operationQueue.maxConcurrentOperationCount = maxConcurrentOperationCount } - public init(label: String?, qos: DispatchQoS?, attributes: DispatchQueue.Attributes?, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency?, target: DispatchQueue?) { - dispatchQueue = DispatchQueue(label: label ?? UUID().uuidString, qos: qos ?? .default, attributes: attributes ?? .concurrent, autoreleaseFrequency: autoreleaseFrequency ?? .inherit, target: target) + public init(label: String?, qos: dispatch_qos_class_t, attributes: dispatch_queue_attr_t?, target: dispatch_queue_t?) { + let attr = dispatch_queue_attr_make_with_qos_class(attributes, qos, QOS_MIN_RELATIVE_PRIORITY) + dispatchQueue = dispatch_queue_create(NSUUID().UUIDString, attr) + dispatch_set_target_queue(dispatchQueue, target) priority = .dispatch } - open func execute(_ operation: Operation) { + public func execute(operation: NSOperation) { operationQueue.addOperation(operation) } - open func execute(_ operations: [Operation], waitUntilFinished: Bool = false) { + public func execute(operations: [NSOperation], waitUntilFinished: Bool = false) { operationQueue.addOperations(operations, waitUntilFinished: waitUntilFinished) } - open func execute(_ block: @escaping () -> Void) -> Any { + public func execute(block: () -> Void) -> Any { if priority == .dispatch { - return execute(qos: nil, flags: nil, block: block) + return execute(block as dispatch_block_t) } else { - let blockOperation = BlockOperation(block: block) + let blockOperation = NSBlockOperation(block: block) execute(blockOperation) return blockOperation } } - open func execute(_ blocks: [() -> Void], concurrent: Bool = true, waitUntilFinished: Bool = false) -> [Any] { + public func execute(blocks: [() -> Void], waitUntilFinished: Bool = false) -> [Any] { var actions = [Any]() - if concurrent { - for block in blocks { - actions.append(execute(block)) - } - } - else { - for block in blocks { - let blockOperation = BlockOperation(block: block) - if let lastOperation = actions.last as? Operation { - blockOperation.addDependency(lastOperation) - } - actions.append(blockOperation) - } - if let operations = actions as? [Operation] { - execute(operations, waitUntilFinished: waitUntilFinished) - } + for block in blocks { + actions.append(execute(block)) } return actions } - open func execute(qos: DispatchQoS?, flags: DispatchWorkItemFlags?, block: @escaping @convention(block) () -> ()) -> DispatchWorkItem { - let work = DispatchWorkItem(qos: qos ?? .default, flags: flags ?? .assignCurrentContext, block: block) - execute(work) - return work - } - - open func execute(_ work: DispatchWorkItem) { - dispatchQueue.async(execute: work) + public func execute(block: dispatch_block_t) -> dispatch_block_t { + dispatch_async(dispatchQueue, block) + return block } } diff --git a/Kommander/Kommand.swift b/Kommander/Kommand.swift index 0e7f732..859ab29 100644 --- a/Kommander/Kommand.swift +++ b/Kommander/Kommand.swift @@ -8,11 +8,11 @@ import Foundation -open class Kommand { +public class Kommand { public typealias ActionBlock = () throws -> T - public typealias SuccessBlock = (_ result: T) -> Void - public typealias ErrorBlock = (_ error: Error) -> Void + public typealias SuccessBlock = (result: T) -> Void + public typealias ErrorBlock = (error: ErrorType) -> Void private final let deliverer: Dispatcher private final let executor: Dispatcher @@ -21,43 +21,43 @@ open class Kommand { private(set) internal final var errorBlock: ErrorBlock? internal final var action: Any? - public init(deliverer: Dispatcher, executor: Dispatcher, actionBlock: @escaping ActionBlock) { + public init(deliverer: Dispatcher, executor: Dispatcher, actionBlock: ActionBlock) { self.deliverer = deliverer self.executor = executor self.actionBlock = actionBlock } - open func onSuccess(_ onSuccess: @escaping SuccessBlock) -> Self { + public func onSuccess(onSuccess: SuccessBlock) -> Self { self.successBlock = onSuccess return self } - open func onError(_ onError: @escaping ErrorBlock) -> Self { + public func onError(onError: ErrorBlock) -> Self { self.errorBlock = onError return self } - open func execute() { + public func execute() { action = executor.execute { do { let result = try self.actionBlock() _ = self.deliverer.execute { - self.successBlock?(result) + self.successBlock?(result: result) } } catch { _ = self.deliverer.execute { - self.errorBlock?(error) + self.errorBlock?(error: error) } } } } - open func cancel() { - if let operation = action as? Operation, operation.isExecuting { + public func cancel() { + if let operation = action as? NSOperation where operation.executing { operation.cancel() } - else if let work = action as? DispatchWorkItem, !work.isCancelled { - work.cancel() + else if let block = action as? dispatch_block_t where dispatch_block_testcancel(block) == 0 { + dispatch_block_cancel(block) } } diff --git a/Kommander/Kommander.swift b/Kommander/Kommander.swift index 8308b94..90b5fbb 100644 --- a/Kommander/Kommander.swift +++ b/Kommander/Kommander.swift @@ -8,7 +8,7 @@ import Foundation -open class Kommander { +public class Kommander { private final let deliverer: Dispatcher private final let executor: Dispatcher @@ -30,29 +30,29 @@ open class Kommander { self.executor = executor ?? Dispatcher() } - public convenience init(name: String?, qos: QualityOfService?, maxConcurrentOperationCount: Int) { + public convenience init(name: String?, qos: NSQualityOfService?, maxConcurrentOperationCount: Int) { self.init(deliverer: nil, name: name, qos: qos, maxConcurrentOperationCount: maxConcurrentOperationCount) } - public convenience init(name: String?, qos: DispatchQoS?, attributes: DispatchQueue.Attributes?, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency?, target: DispatchQueue?) { - self.init(deliverer: nil, name: name, qos: qos, attributes: attributes, autoreleaseFrequency: autoreleaseFrequency, target: target) + public convenience init(name: String?, qos: dispatch_qos_class_t, attributes: dispatch_queue_attr_t?, target: dispatch_queue_t?) { + self.init(deliverer: nil, name: name, qos: qos, attributes: attributes, target: target) } - public init(deliverer: Dispatcher?, name: String?, qos: QualityOfService?, maxConcurrentOperationCount: Int) { + public init(deliverer: Dispatcher?, name: String?, qos: NSQualityOfService?, maxConcurrentOperationCount: Int) { self.deliverer = deliverer ?? CurrentDispatcher() executor = Dispatcher(name: name, qos: qos, maxConcurrentOperationCount: maxConcurrentOperationCount) } - public init(deliverer: Dispatcher?, name: String?, qos: DispatchQoS?, attributes: DispatchQueue.Attributes?, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency?, target: DispatchQueue?) { + public init(deliverer: Dispatcher?, name: String?, qos: dispatch_qos_class_t, attributes: dispatch_queue_attr_t?, target: dispatch_queue_t?) { self.deliverer = deliverer ?? CurrentDispatcher() - executor = Dispatcher(label: name, qos: qos, attributes: attributes, autoreleaseFrequency: autoreleaseFrequency, target: target) + executor = Dispatcher(label: name, qos: qos, attributes: attributes, target: target) } - open func makeKommand(_ actionBlock: @escaping () throws -> T) -> Kommand { + public func makeKommand(actionBlock: () throws -> T) -> Kommand { return Kommand(deliverer: deliverer, executor: executor, actionBlock: actionBlock) } - open func makeKommands(_ actionBlocks: [() throws -> T]) -> [Kommand] { + public func makeKommands(actionBlocks: [() throws -> T]) -> [Kommand] { var kommands = [Kommand]() for actionBlock in actionBlocks { kommands.append(Kommand(deliverer: deliverer, executor: executor, actionBlock: actionBlock)) @@ -60,28 +60,28 @@ open class Kommander { return kommands } - open func execute(_ kommands: [Kommand], concurrent: Bool = true, waitUntilFinished: Bool = false) { + public func execute(kommands: [Kommand], waitUntilFinished: Bool = false) { let blocks = kommands.map { kommand -> () -> Void in return { do { let result = try kommand.actionBlock() _ = self.deliverer.execute { - kommand.successBlock?(result) + kommand.successBlock?(result: result) } } catch { _ = self.deliverer.execute { - kommand.errorBlock?(error) + kommand.errorBlock?(error: error) } } } } - let actions = executor.execute(blocks, concurrent: concurrent, waitUntilFinished: waitUntilFinished) - for (index, kommand) in kommands.enumerated() { + let actions = executor.execute(blocks, waitUntilFinished: waitUntilFinished) + for (index, kommand) in kommands.enumerate() { kommand.action = actions[index] } } - open func cancel(_ kommands: [Kommand]) { + public func cancel(kommands: [Kommand]) { for kommand in kommands { kommand.cancel() } diff --git a/Kommander/MainDispatcher.swift b/Kommander/MainDispatcher.swift index 83a201c..fbbfa9b 100644 --- a/Kommander/MainDispatcher.swift +++ b/Kommander/MainDispatcher.swift @@ -8,22 +8,22 @@ import Foundation -open class MainDispatcher: Dispatcher { +public class MainDispatcher: Dispatcher { public init() { - super.init(name: nil, qos: nil, maxConcurrentOperationCount: OperationQueue.defaultMaxConcurrentOperationCount) - operationQueue = OperationQueue.main - dispatchQueue = DispatchQueue.main + super.init(name: nil, qos: nil, maxConcurrentOperationCount: NSOperationQueueDefaultMaxConcurrentOperationCount) + operationQueue = NSOperationQueue.mainQueue() + dispatchQueue = dispatch_get_main_queue() } - private override convenience init(name: String?, qos: QualityOfService?, maxConcurrentOperationCount: Int) { + private override convenience init(name: String?, qos: NSQualityOfService?, maxConcurrentOperationCount: Int) { self.init() - assertionFailure("You can't use this initializer for a \(String(describing: type(of: self))).") + assertionFailure("You can't use this initializer for a \(String(self.dynamicType)).") } - private override convenience init(label: String?, qos: DispatchQoS?, attributes: DispatchQueue.Attributes?, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency?, target: DispatchQueue?) { + private override convenience init(label: String?, qos: dispatch_qos_class_t, attributes: dispatch_queue_attr_t?, target: dispatch_queue_t?) { self.init() - assertionFailure("You can't use this initializer for a \(String(describing: type(of: self))).") + assertionFailure("You can't use this initializer for a \(String(self.dynamicType)).") } } diff --git a/KommanderTests/KommanderTests.swift b/KommanderTests/KommanderTests.swift index fe78510..e0348e3 100644 --- a/KommanderTests/KommanderTests.swift +++ b/KommanderTests/KommanderTests.swift @@ -24,9 +24,9 @@ class KommanderTests: XCTestCase { func test_oneCall() { - let ex = expectation(description: String(describing: type(of: self))) + let ex = expectationWithDescription(String(self.dynamicType)) - interactor.getCounter(name: "C1", to: 3) + interactor.getCounter("C1", to: 3) .onSuccess({ (name) in ex.fulfill() }) @@ -35,16 +35,16 @@ class KommanderTests: XCTestCase { XCTFail() }).execute() - waitForExpectations(timeout: 100, handler: nil) + waitForExpectationsWithTimeout(100, handler: nil) } func test_twoCalls() { - let ex = expectation(description: String(describing: type(of: self))) + let ex = expectationWithDescription(String(self.dynamicType)) var successes = 0 - let k1 = interactor.getCounter(name: "C1", to: 3) + let k1 = interactor.getCounter("C1", to: 3) .onSuccess({ (name) in successes+=1 if successes>=2 { @@ -56,7 +56,7 @@ class KommanderTests: XCTestCase { XCTFail() }) - let k2 = interactor.getCounter(name: "C2", to: 5) + let k2 = interactor.getCounter("C2", to: 5) .onSuccess({ (name) in successes+=1 if successes>=2 { @@ -71,18 +71,18 @@ class KommanderTests: XCTestCase { k1.execute() k2.execute() - waitForExpectations(timeout: 100, handler: nil) + waitForExpectationsWithTimeout(100, handler: nil) } func test_nCalls() { - let ex = expectation(description: String(describing: type(of: self))) + let ex = expectationWithDescription(String(self.dynamicType)) var successes = 0 let calls = Int(arc4random_uniform(10) + 1) for i in 0..=calls { @@ -96,12 +96,12 @@ class KommanderTests: XCTestCase { .execute() } - waitForExpectations(timeout: 100, handler: nil) + waitForExpectationsWithTimeout(100, handler: nil) } func test_nCalls_concurrent_waitUntilFinished() { - let ex = expectation(description: String(describing: type(of: self))) + let ex = expectationWithDescription(String(self.dynamicType)) var successes = 0 let calls = Int(arc4random_uniform(10) + 1) @@ -109,7 +109,7 @@ class KommanderTests: XCTestCase { var kommands = [Kommand]() for i in 0..=calls { @@ -122,14 +122,14 @@ class KommanderTests: XCTestCase { })) } - interactor.kommander.execute(kommands, concurrent: true, waitUntilFinished: true) + interactor.kommander.execute(kommands, waitUntilFinished: true) - waitForExpectations(timeout: 100, handler: nil) + waitForExpectationsWithTimeout(100, handler: nil) } func test_nCalls_concurrent() { - let ex = expectation(description: String(describing: type(of: self))) + let ex = expectationWithDescription(String(self.dynamicType)) var successes = 0 let calls = Int(arc4random_uniform(10) + 1) @@ -137,7 +137,7 @@ class KommanderTests: XCTestCase { var kommands = [Kommand]() for i in 0..=calls { @@ -150,65 +150,9 @@ class KommanderTests: XCTestCase { })) } - interactor.kommander.execute(kommands, concurrent: true, waitUntilFinished: false) + interactor.kommander.execute(kommands, waitUntilFinished: false) - waitForExpectations(timeout: 100, handler: nil) - } - - func test_nCalls_sequential_waitUntilFinished() { - - let ex = expectation(description: String(describing: type(of: self))) - - var successes = 0 - let calls = Int(arc4random_uniform(10) + 1) - - var kommands = [Kommand]() - - for i in 0..=calls { - ex.fulfill() - } - }) - .onError({ (error) in - ex.fulfill() - XCTFail() - })) - } - - interactor.kommander.execute(kommands, concurrent: false, waitUntilFinished: true) - - waitForExpectations(timeout: 100, handler: nil) - } - - func test_nCalls_sequential() { - - let ex = expectation(description: String(describing: type(of: self))) - - var successes = 0 - let calls = Int(arc4random_uniform(10) + 1) - - var kommands = [Kommand]() - - for i in 0..=calls { - ex.fulfill() - } - }) - .onError({ (error) in - ex.fulfill() - XCTFail() - })) - } - - interactor.kommander.execute(kommands, concurrent: false, waitUntilFinished: false) - - waitForExpectations(timeout: 100, handler: nil) + waitForExpectationsWithTimeout(100, handler: nil) } } diff --git a/README.md b/README.md index 821bc48..e63b6d7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ pod 'Kommander' For Swift 2 compatibility use: ```ruby -pod 'Kommander', :git => 'https://gitlab.intelygenz.com/ios/kommander.git', :tag => 'swift2' +pod 'Kommander', :git => 'https://gitlab.intelygenz.com/ios/kommander.git', :tag => '0.2.2-swift2' ``` For Objective-C compatibility use: