gpt4 book ai didi

ios - 我可以在 Swift 中使用 actor 始终在主线程上调用函数吗?

转载 作者:行者123 更新时间:2023-12-04 16:24:37 26 4
gpt4 key购买 nike

我最近看到 Swift 在 Swift 5.5 中为 Actor 模型引入了并发支持。 .当我们有一个共享的、可变的状态时,这个模型支持安全的并发代码以避免数据竞争。
我想避免应用程序 UI 中的主线程数据竞争。为此,我正在包装 DispatchQueue.main.async在我设置的调用站点 UIImageView.image属性(property)或UIButton风格。

// Original function
func setImage(thumbnailName: String) {
myImageView.image = UIImage(named: thumbnailName)
}

// Call site
DispatchQueue.main.async {
myVC.setImage(thumbnailName: "thumbnail")
}
这似乎不安全,因为我必须记住在主队列上手动调度该方法。另一种解决方案如下所示:
func setImage(thumbnailName: String) {
DispatchQueue.main.async {
myImageView.image = UIImage(named: thumbnailName)
}
}
但这看起来像很多样板文件,我不会说我喜欢将它用于具有不止一层嵌套的复杂功能。
Swift 对 Actor 的支持看起来像是一个完美的解决方案。那么,有没有办法让我的代码更安全,即始终使用 Actors 在主线程上调用 UI 函数?

最佳答案

Actor 隔离和重入现在已在 Swift 标准库中实现。因此,Apple 建议将该模型用于具有许多新并发特性的并发逻辑,以避免数据竞争。我们现在有了一个更简洁的替代方案,而不是基于锁的同步(大量样板文件)。
一些 UIKit类,包括 UIViewControllerUILabel , 现在对 @MainActor 提供开箱即用的支持.所以我们只需要在自定义 UI 相关的类中使用注解即可。例如,在上面的代码中,myImageView.image将自动在主队列上分派(dispatch)。然而,UIImage.init(named:)调用不会在 View Controller 之外的主线程上自动分派(dispatch)。
一般情况下,@MainActor对于并发访问 UI 相关状态很有用,并且即使我们也可以手动调度也是最容易做到的。我在下面概述了潜在的解决方案:
方案一
最简单的可能。此属性在 UI 相关类中可能很有用。 Apple 使用 @MainActor 使流程变得更加简洁。方法注释:

@MainActor func setImage(thumbnailName: String) {
myImageView.image = UIImage(image: thumbnailName)
}
这段代码相当于包裹在 DispatchQueue.main.async ,但调用站点现在是:
await setImage(thumbnailName: "thumbnail")
解决方案2
如果你有Custom UI相关的类,我们可以考虑申请 @MainActor到类型本身。这确保所有方法和属性都在主 DispatchQueue 上分派(dispatch)。 .
然后我们可以使用 nonisolated 手动选择退出主线程。非 UI 逻辑的关键字。
@MainActor class ListViewModel: ObservableObject {
func onButtonTap(...) { ... }

nonisolated func fetchLatestAndDisplay() async { ... }
}
我们不需要指定 await当我们明确调用 onButtonTap 时内 actor .
解决方案 3(适用于块和函数)
我们也可以在 actor 之外的主线程上调用函数和:
func onButtonTap(...) async {
await MainActor.run {
....
}
}
里面不一样 actor :
func onButtonTap(...) {
await MainActor.run {
....
}
}
该解决方案比最适合包装 的上述两种解决方案清洁度略低。整个 MainActor 上的功能.然而, actor.run还允许在 actor 之间使用线程间代码合一 func (感谢@Bill 的建议)。
概括
Actor 使 Swift 代码更安全、更简洁、更易于编写。不要过度使用它们,但是将 UI 代码分派(dispatch)到主线程是一个很好的用例。请注意,由于该功能仍处于测试阶段,因此该框架将来可能会进一步更改/改进。
奖金笔记
由于我们可以轻松使用 actor关键字可与 class 互换或 struct ,我想建议将关键字限制在严格需要并发的情况下。使用关键字会增加实例创建的额外开销,因此在没有要管理的共享状态时没有意义。
如果您不需要共享状态,则不要不必要地创建它。 struct实例创建非常轻量级,大多数时候最好创建一个新实例。例如 SwiftUI .

关于ios - 我可以在 Swift 中使用 actor 始终在主线程上调用函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67893376/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com