Skip to content
This repository has been archived by the owner on Feb 28, 2020. It is now read-only.

Commit

Permalink
Merge branch 'release/2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmartinelli committed Nov 7, 2015
2 parents c2ab771 + b7ac1eb commit d6c38e2
Show file tree
Hide file tree
Showing 16 changed files with 678 additions and 602 deletions.
Binary file added AlecrimAsyncKit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion AlecrimAsyncKit.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "AlecrimAsyncKit"
s.version = "2.0-beta.1"
s.version = "2.0"
s.summary = "Bringing async and await to Swift world with some flavouring."
s.homepage = "https://github.com/Alecrim/AlecrimAsyncKit"

Expand Down
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#AlecrimAsyncKit
![AlecrimAsyncKit](https://raw.githubusercontent.com/Alecrim/AlecrimAsyncKit/master/AlecrimAsyncKit.png)

[![Language: Swift](https://img.shields.io/badge/lang-Swift-orange.svg?style=flat)](https://developer.apple.com/swift/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/Alecrim/AlecrimAsyncKit/develop/LICENSE)
[![CocoaPods](https://img.shields.io/cocoapods/v/AlecrimAsyncKit.svg?style=flat)](http://cocoapods.org)
[![Forks](https://img.shields.io/github/forks/Alecrim/AlecrimAsyncKit.svg?style=flat)](https://github.com/Alecrim/AlecrimAsyncKit/network)
[![Stars](https://img.shields.io/github/stars/Alecrim/AlecrimAsyncKit.svg?style=flat)](https://github.com/Alecrim/AlecrimAsyncKit/stargazers)

Bringing async and await to Swift world with some flavouring.

Expand Down Expand Up @@ -206,13 +212,24 @@ Only failable tasks can be cancelled.

#### The main thread

Even if you cannot "await" a task on main thread, you still can start a background task from the main thread and handle its completion using the `didFinish` method. If the queue parameter is not added, the callback closure will be called on the main thread.
Even if you cannot "await" a task on main thread, you still can start a background task from the main thread. If you want to handle its completion you may use `TaskWaiter` helper class. If the queue parameter is not added, the callback closures will be called on the main thread.

```swift
// this code is running on the main thread
asyncCalculate()
.didFinish { value, error in
if let error = error {
TaskWaiter(task: asyncCalculate())
.didFinishWithValue { value in
print("The result is \(value)")
}
.didFinishWithError { error in
// do a nice error handling here
}
.didCancel {
print("Task was cancelled")
}
.didFinish { task in
// this closure will be always called, even if the task was cancelled

if let error = error where !error.userCancelled {
// do a nice error handling here
}
else {
Expand Down Expand Up @@ -240,7 +257,7 @@ func asyncCalculate() -> Task<Int> {
}
```

The difference between a failable task and a non-failable task is that a non-failable does not have the `error` parameter in its `didFinish` closure. A failable task has also a `didCancel` method (note that the `didFinish` closure will be called even if the task was cancelled).
The difference between a failable task and a non-failable task is that a non-failable task waiter is called `NonFailableTaskWaiter` and it does not have the `didFinishWithError` and `didCancel` methods.

### Considerations

Expand Down
24 changes: 12 additions & 12 deletions Source/AlecrimAsyncKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
1413F62C1BDCAE56001049D5 /* TaskState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1413F62B1BDCAE56001049D5 /* TaskState.swift */; };
1413F62E1BDCAE8B001049D5 /* TaskType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1413F62D1BDCAE8B001049D5 /* TaskType.swift */; };
1416E08D1BDC931A00F1EA73 /* TaskObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1416E08C1BDC931A00F1EA73 /* TaskObserver.swift */; };
142561B51BE31B9D00A4C974 /* TaskOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142561B41BE31B9D00A4C974 /* TaskOperation.swift */; };
143045511BB7AB5900CD0AED /* ProcessInfoActivityTaskObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 143045501BB7AB5900CD0AED /* ProcessInfoActivityTaskObserver.swift */; };
14749B841B9C437700661E98 /* EventStorePermissionTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14749B831B9C437700661E98 /* EventStorePermissionTaskCondition.swift */; };
14749B861B9C4DA300661E98 /* BooleanTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14749B851B9C4DA300661E98 /* BooleanTaskCondition.swift */; };
Expand All @@ -21,7 +21,7 @@
148513A11B9BD15100FAB0FA /* PhotosPermissionTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513911B9BD15100FAB0FA /* PhotosPermissionTaskCondition.swift */; };
148513A21B9BD15100FAB0FA /* ReachabilityTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513921B9BD15100FAB0FA /* ReachabilityTaskCondition.swift */; };
148513A31B9BD15100FAB0FA /* RemoteNotificationPermissionTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513931B9BD15100FAB0FA /* RemoteNotificationPermissionTaskCondition.swift */; };
148513A41B9BD15100FAB0FA /* TaskBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513951B9BD15100FAB0FA /* TaskBuilder.swift */; };
148513A41B9BD15100FAB0FA /* AsyncAwait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513951B9BD15100FAB0FA /* AsyncAwait.swift */; };
148513A51B9BD15100FAB0FA /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513961B9BD15100FAB0FA /* Errors.swift */; };
148513A61B9BD15100FAB0FA /* MutuallyExclusiveTaskCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513971B9BD15100FAB0FA /* MutuallyExclusiveTaskCondition.swift */; };
148513A71B9BD15100FAB0FA /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148513981B9BD15100FAB0FA /* Task.swift */; };
Expand All @@ -34,9 +34,9 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
1413F62B1BDCAE56001049D5 /* TaskState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskState.swift; sourceTree = "<group>"; };
1413F62D1BDCAE8B001049D5 /* TaskType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskType.swift; sourceTree = "<group>"; };
1416E08C1BDC931A00F1EA73 /* TaskObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskObserver.swift; sourceTree = "<group>"; };
142561B41BE31B9D00A4C974 /* TaskOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskOperation.swift; sourceTree = "<group>"; };
143045501BB7AB5900CD0AED /* ProcessInfoActivityTaskObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessInfoActivityTaskObserver.swift; sourceTree = "<group>"; };
14749B831B9C437700661E98 /* EventStorePermissionTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventStorePermissionTaskCondition.swift; sourceTree = "<group>"; };
14749B851B9C4DA300661E98 /* BooleanTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BooleanTaskCondition.swift; sourceTree = "<group>"; };
Expand All @@ -48,7 +48,7 @@
148513911B9BD15100FAB0FA /* PhotosPermissionTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotosPermissionTaskCondition.swift; sourceTree = "<group>"; };
148513921B9BD15100FAB0FA /* ReachabilityTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReachabilityTaskCondition.swift; sourceTree = "<group>"; };
148513931B9BD15100FAB0FA /* RemoteNotificationPermissionTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteNotificationPermissionTaskCondition.swift; sourceTree = "<group>"; };
148513951B9BD15100FAB0FA /* TaskBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskBuilder.swift; sourceTree = "<group>"; };
148513951B9BD15100FAB0FA /* AsyncAwait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncAwait.swift; sourceTree = "<group>"; };
148513961B9BD15100FAB0FA /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
148513971B9BD15100FAB0FA /* MutuallyExclusiveTaskCondition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutuallyExclusiveTaskCondition.swift; sourceTree = "<group>"; };
148513981B9BD15100FAB0FA /* Task.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -100,10 +100,10 @@
148513941B9BD15100FAB0FA /* Core */ = {
isa = PBXGroup;
children = (
148513951B9BD15100FAB0FA /* AsyncAwait.swift */,
148513981B9BD15100FAB0FA /* Task.swift */,
1413F62D1BDCAE8B001049D5 /* TaskType.swift */,
1413F62B1BDCAE56001049D5 /* TaskState.swift */,
148513951B9BD15100FAB0FA /* TaskBuilder.swift */,
142561B41BE31B9D00A4C974 /* TaskOperation.swift */,
14C2903F1BDE544B006F1BB3 /* TaskWaiter.swift */,
148513961B9BD15100FAB0FA /* Errors.swift */,
148513991B9BD15100FAB0FA /* TaskCondition.swift */,
Expand Down Expand Up @@ -250,7 +250,6 @@
files = (
148513A11B9BD15100FAB0FA /* PhotosPermissionTaskCondition.swift in Sources */,
14C290401BDE544B006F1BB3 /* TaskWaiter.swift in Sources */,
1413F62C1BDCAE56001049D5 /* TaskState.swift in Sources */,
148513A01B9BD15100FAB0FA /* PassLibraryAvailableCondition.swift in Sources */,
148513A31B9BD15100FAB0FA /* RemoteNotificationPermissionTaskCondition.swift in Sources */,
148513A81B9BD15100FAB0FA /* TaskCondition.swift in Sources */,
Expand All @@ -259,11 +258,12 @@
1485139E1B9BD15100FAB0FA /* NegateTaskCondition.swift in Sources */,
148513A61B9BD15100FAB0FA /* MutuallyExclusiveTaskCondition.swift in Sources */,
148513B11B9BD9A500FAB0FA /* TimeoutTaskObserver.swift in Sources */,
142561B51BE31B9D00A4C974 /* TaskOperation.swift in Sources */,
1413F62E1BDCAE8B001049D5 /* TaskType.swift in Sources */,
148513A21B9BD15100FAB0FA /* ReachabilityTaskCondition.swift in Sources */,
148513A71B9BD15100FAB0FA /* Task.swift in Sources */,
148513A51B9BD15100FAB0FA /* Errors.swift in Sources */,
148513A41B9BD15100FAB0FA /* TaskBuilder.swift in Sources */,
148513A41B9BD15100FAB0FA /* AsyncAwait.swift in Sources */,
148513AE1B9BD38100FAB0FA /* LocationPermissionTaskCondition.swift in Sources */,
1485139D1B9BD15100FAB0FA /* DelayTaskCondition.swift in Sources */,
1485139F1B9BD15100FAB0FA /* SilentTaskCondition.swift in Sources */,
Expand Down Expand Up @@ -315,7 +315,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
Expand Down Expand Up @@ -361,7 +361,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator watchos watchsimulator";
Expand All @@ -379,7 +379,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 149;
CURRENT_PROJECT_VERSION = 163;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -401,7 +401,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 149;
CURRENT_PROJECT_VERSION = 163;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ public final class TimeoutTaskObserver: TaskObserver {
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * Double(NSEC_PER_SEC)))

let queue: dispatch_queue_t
if #available(OSXApplicationExtension 10.10, *) {
queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
} else {
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
}
queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)

dispatch_after(when, queue) {
weakTask?.cancel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,22 +109,8 @@ public final class RemoteNotificationPermissionTaskCondition: TaskCondition {

extension UIApplication {

private struct AssociatedKeys {
private static var remoteNotificationPermissionTaskCondition = "com.alecrim.AlecrimAsyncKit.UIApplication.RemoteNotificationPermissionTaskCondition"
}

public var remoteNotificationPermissionTaskCondition: RemoteNotificationPermissionTaskCondition {
get {
if let value = objc_getAssociatedObject(self, &AssociatedKeys.remoteNotificationPermissionTaskCondition) as? RemoteNotificationPermissionTaskCondition {
return value
}
else {
let newValue = RemoteNotificationPermissionTaskCondition(application: self)
objc_setAssociatedObject(self, &AssociatedKeys.remoteNotificationPermissionTaskCondition, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

return newValue
}
}
public func remoteNotificationPermissionTaskCondition() -> RemoteNotificationPermissionTaskCondition {
return RemoteNotificationPermissionTaskCondition(application: self)
}

}
Expand Down
127 changes: 127 additions & 0 deletions Source/AlecrimAsyncKit/Core/AsyncAwait.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//
// AsyncAwait.swift
// AlecrimAsyncKit
//
// Created by Vanderlei Martinelli on 2015-05-10.
// Copyright (c) 2015 Alecrim. All rights reserved.
//

import Foundation

private let _defaultTaskQueue: NSOperationQueue = {
let queue = NSOperationQueue()
queue.name = "com.alecrim.AlecrimAsyncKit.Task"
queue.qualityOfService = .Default
queue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount

return queue
}()

// MARK: -

public typealias TaskPriority = NSOperationQueuePriority

// MARK: - async

@warn_unused_result
public func async<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, observers: [TaskObserver]? = nil, closure: () -> V) -> NonFailableTask<V> {
return asyncEx(queue, qualityOfService: qualityOfService, observers: observers) { task in
let value = closure()
task.finishWithValue(value)
}
}

@warn_unused_result
public func async<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, condition: TaskCondition, observers: [TaskObserver]? = nil, closure: () throws -> V) -> Task<V> {
return async(queue, qualityOfService: qualityOfService, conditions: [condition], observers: observers, closure: closure)
}

@warn_unused_result
public func async<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, conditions: [TaskCondition]? = nil, observers: [TaskObserver]? = nil, closure: () throws -> V) -> Task<V> {
return asyncEx(queue, qualityOfService: qualityOfService, observers: observers) { task in
do {
let value = try closure()
task.finishWithValue(value)
}
catch let error {
task.finishWithError(error)
}
}
}

// MARK: - asyncEx

@warn_unused_result
public func asyncEx<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, taskPriority: TaskPriority? = nil, observers: [TaskObserver]? = nil, closure: (NonFailableTask<V>) -> Void) -> NonFailableTask<V> {
return taskWithQueue(queue, qualityOfService: qualityOfService, taskPriority: taskPriority, conditions: nil, observers: observers, closure: closure)
}

@warn_unused_result
public func asyncEx<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, taskPriority: TaskPriority? = nil, condition: TaskCondition, observers: [TaskObserver]? = nil, closure: (Task<V>) -> Void) -> Task<V> {
return asyncEx(queue, qualityOfService: qualityOfService, taskPriority: taskPriority, conditions: [condition], observers: observers, closure: closure)
}


@warn_unused_result
public func asyncEx<V>(queue: NSOperationQueue = _defaultTaskQueue, qualityOfService: NSQualityOfService? = nil, taskPriority: TaskPriority? = nil, conditions: [TaskCondition]? = nil, observers: [TaskObserver]? = nil, closure: (Task<V>) -> Void) -> Task<V> {
return taskWithQueue(queue, qualityOfService: qualityOfService, taskPriority: taskPriority, conditions: conditions, observers: observers, closure: closure)
}


// MARK: - await

public func await<V>(@noescape closure: () -> NonFailableTask<V>) -> V {
let task = closure()
return await(task)
}

public func await<V>(task: NonFailableTask<V>) -> V {
task.waitUntilFinished()
return task.value
}

public func await<V>(@noescape closure: () -> Task<V>) throws -> V {
let task = closure()
return try await(task)
}

public func await<V>(task: Task<V>) throws -> V {
task.waitUntilFinished()

if let error = task.error {
throw error
}

return task.value
}


// MARK: -

private func taskWithQueue<T: InitializableTaskType>(queue: NSOperationQueue, qualityOfService: NSQualityOfService?, taskPriority: TaskPriority?, conditions: [TaskCondition]?, observers: [TaskObserver]?, closure: (T) -> Void) -> T {
assert(queue.maxConcurrentOperationCount == NSOperationQueueDefaultMaxConcurrentOperationCount || queue.maxConcurrentOperationCount > 1, "Task `queue` cannot be the main queue nor a serial queue.")

//
let task = T(conditions: conditions, observers: observers, closure: closure)

//
if let operation = task as? TaskOperation {
if let qualityOfService = qualityOfService {
operation.qualityOfService = qualityOfService
}

if let taskPriority = taskPriority {
operation.queuePriority = taskPriority
}

//
operation.willEnqueue()
queue.addOperation(operation)
}
else {
fatalError()
}

//
return task
}
Loading

0 comments on commit d6c38e2

Please sign in to comment.