AsyncSwift 2.0.4

AsyncSwift 2.0.4

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2017年10月
SwiftSwift 版本4.0
SPM支持 SPM

Tobias Due Munk维护。



  • 作者:
  • Tobias Due Munk

Async

现在是 Swift 中在 Grand Central Dispatch (GCD) 中进行异步派发的语法糖,比 GCD 的语法要简洁

Async 语法如下

Async.userInitiated {
    return 10
}.background {
    return "Score: \($0)"
}.main {
    label.text = $0
}

尽管 GCD 在 Swift 3.0 中已经有了相当不错的语法,但与上面的语法比较

DispatchQueue.global(qos: .userInitiated).async {
    let value = 10
    DispatchQueue.global(qos: .background).async {
        let text = "Score: \(value)"
        DispatchQueue.main.async {
            label.text = text
        }
    }
}

AsyncGroup 语法如下

let group = AsyncGroup()
group.background {
    print("This is run on the background queue")
}
group.background {
    print("This is also run on the background queue in parallel")
}
group.wait()
print("Both asynchronous blocks are complete")

安装

优势

  1. 通过链式使用避免代码缩进
  2. 参数和返回类型减少污染的范围

您能做什么

支持现代队列类

Async.main {}
Async.userInteractive {}
Async.userInitiated {}
Async.utility {}
Async.background {}

链接任意数量的块

Async.userInitiated {
    // 1
}.main {
    // 2
}.background {
    // 3
}.main {
    // 4
}

存储引用以供稍后链接

let backgroundBlock = Async.background {
    print("This is run on the background queue")
}

// Run other code here...

// Chain to reference
backgroundBlock.main {
    print("This is run on the \(qos_class_self().description) (expected \(qos_class_main().description)), after the previous block")
}

自定义队列

let customQueue = DispatchQueue(label: "CustomQueueLabel", attributes: [.concurrent])
let otherCustomQueue = DispatchQueue(label: "OtherCustomQueueLabel")
Async.custom(queue: customQueue) {
    print("Custom queue")
}.custom(queue: otherCustomQueue) {
    print("Other custom queue")
}

延迟后发送块

let seconds = 0.5
Async.main(after: seconds) {
    print("Is called after 0.5 seconds")
}.background(after: 0.4) {
    print("At least 0.4 seconds after previous block, and 0.9 after Async code is called")
}

取消尚未发送的块

// Cancel blocks not yet dispatched
let block1 = Async.background {
    // Heavy work
    for i in 0...1000 {
        print("A \(i)")
    }
}
let block2 = block1.background {
    print("B – shouldn't be reached, since cancelled")
}
Async.main {
    // Cancel async to allow block1 to begin
    block1.cancel() // First block is _not_ cancelled
    block2.cancel() // Second block _is_ cancelled
}

等待块完成 - 在后台任务后简化在当前队列中继续的方式

let block = Async.background {
    // Do stuff
}

// Do other stuff

block.wait()

它是如何工作的

通过在 OS X 10.10 和 iOS 8 中引入的 GCD 的新通知 API 来实现它。每次链式块被调用时,先前的队列已经完成。

let previousBlock = {}
let chainingBlock = {}
let dispatchQueueForChainingBlock = ...

// Use the GCD API to extend the blocks
let _previousBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, previousBlock)
let _chainingBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, chainingBlock)

// Use the GCD API to call back when finishing the "previous" block
dispatch_block_notify(_previousBlock, dispatchQueueForChainingBlock, _chainingBlock)

链式语法的部分是通过类方法在 Async 对象上实现的,例如 Async.main {} 返回一个结构体。该结构体有相匹配的方法,例如 theStruct.main {}

已知的错误

现代 GCD 队列在 iOS 模拟器中工作不正常。请参阅问题1322

已知的改进

无法扩展 dispatch_block_t。采用的解决方案:将 dispatch_block_t 包装在一个包含将块作为属性的结构体中。

应用

还有一个用于快速并行化 for 循环的 dispatch_apply() 的包装器。

Apply.background(100) { i in
    // Do stuff e.g. print(i)
}

请注意,此函数在运行100次块之后返回,即它是非异步的。对于异步行为,使用Async块包装它,例如:Async.background { Apply.background(100) { ... } }

AsyncGroup

AsyncGroup简化了对异步块组的管理。

GCD的多重分派

let group = AsyncGroup()
group.background {
    // Run on background queue
}
group.utility {
    // Run on utility queue, in parallel to the previous block
}
group.wait()

所有现代队列类

group.main {}
group.userInteractive {}
group.userInitiated {}
group.utility {}
group.background {}

自定义队列

let customQueue = dispatch_queue_create("Label", DISPATCH_QUEUE_CONCURRENT)
group.custom(queue: customQueue) {}

等待组完成

let group = AsyncGroup()
group.background {
    // Do stuff
}
group.background {
    // Do other stuff in parallel
}
// Wait for both to finish
group.wait()
// Do rest of stuff

自定义异步操作

let group = AsyncGroup()
group.enter()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // Do stuff
    group.leave()
}
group.enter()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // Do other stuff in parallel
    group.leave()
}
// Wait for both to finish
group.wait()
// Do rest of stuff

许可协议

MIT许可协议(MIT)

版权所有 © 2016 Tobias Due Munk

在此授予任何人免费获得此软件及其相关文档副本(以下简称“软件”)、在不加限制的情况下处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或将软件的副本进行销售的权力,并允许其将软件提供给他人以待使用,前提是满足以下条件:

上述版权声明和本许可声明应包含于软件的副本或实质性组成部分中。

软件按“原样”提供,不提供任何保证,明示或暗示的保证,包括但不限于适用性、特定目的的适用性和非侵权性。在任何情况下,作者或版权所有者都不对任何主张、损害或其他责任承担任何责任,无论这些责任是基于合同、侵权或其他法律适用,起源于、源于或与软件或其使用或任何其他方式相关。