Chary

Chary 是一个 DispatchQueue 实用工具,用于更安全地进行同步和异步编程。它可以帮助您在处理多线程应用程序时避免竞争条件。

Codacy Badge build test SwiftPM Compatible Version License Platform

要求

安装

Cocoapods

Chary 可通过 CocoaPods 获得。要安装它,只需将以下行添加到您的 Podfile 中

pod 'Chary'

来自 XCode 的 Swift Package Manager

来自 Package.swift 的 Swift Package Manager

Package.swift 中添加为您的目标依赖项

dependencies: [
  .package(url: "https://github.com/hainayanda/Chary.git", .upToNextMajor(from: "1.0.7"))
]

在您的目标中使用它作为 Chary

 .target(
    name: "MyModule",
    dependencies: ["Chary"]
)

作者

Nayanda Haberty, hainayanda@outlook.com

许可证

Pharos 在 MIT 许可下可用。有关更多信息,请参见 LICENSE 文件。


基本用法

Chary 提供了两个实用工具,Atomic 属性包装器和 DispatchQueue 扩展

Atomic 属性包装器

Atomic 属性包装器是一个属性包装器,用于包装一个属性,以便可以原子地访问和编辑它

class MyClass {
    @Atomic var atomicString: String = "atomicString"
    ...
    ...
}

那么,无论在哪里访问或编辑 atomicString,它都是线程安全的。

DispatchQueue.main.async {
    myClass.atomicString = "from main thread"
}
DispatchQueue.global().async {
    myClass.atomicString = "from global thread"
}

DispatchQueue 扩展

Chary 具有一些 DispatchQueue 扩展,这些扩展将在处理多线程时有所帮助。

检查当前队列

您可以使用 isCurrentQueue(is:) 检查当前的 DispatchQueue,该方法将检查给定的队列是否为当前队列。

myQueue = DispatchQueue(label: "myQueue")
myQueue.sync {
    // this will print true
    print(DispatchQueue.isCurrentQueue(is: myQueue))
}
// this will print false
print(DispatchQueue.isCurrentQueue(is: myQueue))

它所做的是注册给定的 DispatchQueue 以进行检测,并将当前可检测的队列与给定的队列进行比较。

public static func isCurrentQueue(is queue: DispatchQueue) -> Bool {
    queue.registerDetection()
    return current == queue
}

调用 DispatchQueue.current 并不能保证返回当前的 DispatchQueue,因为它只能返回已经注册用于检测的 DispatchQueue。 当调用 current 时,有一些默认的 DispatchQueue 会自动注册。

除此之外,它需要手动调用 registerDetection() 以允许通过调用 DispatchQueue.current 来访问 DispatchQueue。 由于 isCurrentQueue(is:) 将自动注册给定的 DispatchQueue,因此传递的队列将在之后可以通过 DispatchQueue.current 访问。

安全同步

如果在同一个 DispatchQueue 中调用,从 DispatchQueue 运行 sync 有时会引发异常。 为了避免这种情况,您可以使用 safeSync 代替,它将首先检查当前队列,并决定是需要立即运行该块,还是使用默认的 sync。 您无需注册 DispatchQueue,因为它会在检查之前自动注册 DispatchQueue

DispatchQueue.main.safeSync {
    print("this will safely executed")
}

如果需要,异步执行

有时,如果您在正确的 DispatchQueue 中,则希望立即执行操作,而不是使用 async 异步运行它。 例如,当您更新 UI 时,如果您已经在 DispatchQueue.main 中,最好立即运行它,而不是将其放入异步队列中。 您可以使用 asyncIfNeeded 立即实现该功能。 它将检查当前的 DispatchQueue,并决定是需要立即运行还是使用默认的 async。 您无需注册 DispatchQueue,因为它会在检查之前自动注册 DispatchQueue

DispatchQueue.main.asyncIfNeeded {
    print("this will executed right away or asynchronously if in different queue")
}

贡献

你知道怎么做。 只需克隆并进行 pull request