一个小型软件包,提供实用工具以帮助处理 Swift 并发
如果您不想添加依赖项,也可以直接将您需要的内容复制粘贴到您的项目中。我不会介意的(哈!)。
功能特点
DispatchQueue.mainActor
,用于与 @MainActor
兼容的 DispatchQueue
代理OperationQueue.mainActor
,用于与 @MainActor
兼容的 OperationQueue
代理UnsafeBlockOperation
,用于不进行 Sendable
检查的 BlockOperation
OperationQueue
的扩展,可以直接提交代码块而无需 Sendable
检查NotificationCenter
的 addUnsafeObserver(forName:object:queue:using:)
ThreadExecutor
,可用于使用专用线程 + 运行循环来支持 actorRunLoop.turn
,用于在异步上下文中更好地控制运行循环Dispatch
// MainActor proxy
let mainQueue = DispatchQueue.mainActor
mainQueue.async {
// statically MainActor
}
let group = DispatchGroup()
// an overload to integrate with DispatchGroup
group.notify(queue: mainQueue) {
// statically MainActor
}
OperationQueue
// MainActor proxy
let mainQueue = OperationQueue.mainActor
mainQueue.addOperation {
// statically MainActor
}
// Unsafe variants
let op = UnsafeBlockOperation {
// non-Sendable captures ok
}
operationQueue.addOperation(op)
queue.addUnsafeOperation {
// non-Sendable captures ok
}
queue.addUnsafeBarrierBlock {
// non-Sendable captures ok
}
NotificationCenter
NotificationCenter.default.addUnsafeObserver(forName: noteName, object: nil, queue: nil) {
// no Sendable requirements here
}
// this will assert if notification is delievered off the MainActor at runtime
NotificationCenter.default.addMainActorObserver(forName: noteName, object: nil) { notification in
// statically MainActor with full access to Notification object
}
UndoManager
undoManager.registerMainActorUndo(withTarget: someView) { target in
// statically MainActor here
}
RunLoop
扩展
// Guarantee that the current RunLoop turns at least once
await RunLoop.turn()
您可以使用 ThreadExecutor
来实现一个 actor,使其所有方法都在具有功能性运行循环的专用线程上运行。这在概念上类似于 MainActor
的工作方式。
如果您想与基于 RunLoop 的 API 交互,这将非常有用。您也可以使用它来降低同步阻塞 actor 执行的死锁风险。但请注意,创建和切换到 ThreadExecutor
actor 都可能比传统的 actor 昂贵得多。
actor ThreadActor {
private let executor = ThreadExecutor(name: "my thread")
nonisolated var unownedExecutor: UnownedSerialExecutor {
executor.asUnownedSerialExecutor()
}
func runsOnThread() {
// This will always execute on the same thread
}
}
dependencies: [
.package(url: "https://github.com/mattmassicotte/MainOffender", from: "0.1.0")
]
我很乐意听到您的声音!请通过 mastodon、issue 或 pull request 与我联系。
我更喜欢协作,如果您有类似的项目,我很乐意找到合作的方式。
为了提高可访问性,我更喜欢使用制表符进行缩进。但是,我更希望您使用您喜欢的系统并提交 PR,而不是因为空格而犹豫不决。
参与此项目即表示您同意遵守贡献者行为准则。