问题标签 [swift-concurrency]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
480 浏览

ios - 为什么要使用 @MainActor 注释 SwiftUI 视图模型?

我一直在观看 Apple 在 WWDC21 上的并发讨论,并阅读了大量有关 Apple 并发更新的文章;但是,我无法解决一件事:为什么人们会提供指导,告诉您应该使用 注释视图模型@MainActor?根据我的阅读,通过将视图模型属性设置为 a@StateObject@ObservedObject在视图中,它会自动变为@MainActor. 那么如果是这样的话,为什么人们仍然建议将视图模型注释为@MainActor

对于上下文,这里有一些我读过的文章参考了这个:

  1. https://www.hackingwithswift.com/quick-start/concurrency/understanding-how-global-actor-inference-works
  2. https://www.hackingwithswift.com/books/concurrency/how-to-use-mainactor-to-run-code-on-the-main-queue
  3. https://peterfriese.dev/swiftui-concurrency-essentials-part1/

摘自第一个链接:

[A] 任何使用带有 @MainActor 的属性包装器的结构或类作为其包装值将自动成为 @MainActor。这就是 @StateObject 和 @ObservedObject 在使用它们的 SwiftUI 视图上传达主要角色的原因——如果你在 SwiftUI 视图中使用这两个属性包装器中的任何一个,整个视图也会变成 @MainActor。

摘自第二个链接:

[W]无论何时你在视图中使用@StateObject 或@ObservedObject,Swift 都会确保整个视图在主要参与者上运行,这样你就不会意外地尝试以危险的方式发布 UI 更新。更好的是,无论您使用什么属性包装器,您的 SwiftUI 视图的 body 属性始终在主要参与者上运行。

这是否意味着您不需要将@MainActor 显式添加到可观察对象?好吧,不——将@MainActor 与这些类一起使用仍然有好处,尤其是如果它们使用 async/await 来完成自己的异步工作,例如从服务器下载数据。

总而言之,如果它会自动为我们处理,我对指导有点困惑。特别是因为我不知道在 SwiftUI 中有一个不是@ObservableObject.

我的最后一个问题,与第一个问题有关,是:如果@StateObject并且@ObservedObject自动生成视图@MainActor,那么是否@EnvironmentObject也生成视图@MainActor

为了在这之后添加一些代码,我打算使用以下类将以下类注入环境中.environmentObject(...)

以下是我的一个视图的视图模型:

如您所见,我已经创建了两个类@ObservableObjects,所以我觉得我应该能够删除@MainActor注释。

任何帮助将不胜感激!谢谢你的时间!

0 投票
0 回答
84 浏览

swift - NSAlert.runModal() 从 Task.init {} 调用时崩溃

谁能告诉我为什么从下面的函数NSAlert.runModal()内部调用时会崩溃。Task.init {}

日志报告说这是在主线程上运行的,那么为什么会崩溃呢?

如果我把它包起来,DispatchQueue.main.async { }那么它工作正常。

isBusy 属性绑定到启动按钮的启用状态,这不会抱怨从后台线程调用。

Task.init {}这是一个错误还是我在使用将异步函数包装在 a 中时做错了viewController什么?

编辑:这似乎有效

0 投票
2 回答
61 浏览

swift - 如何等到来自网络调用的数据到来,然后才返回函数的值#Swift

我有一个服务类,它进行 api 调用并将数据存储到其属性中。然后我的交互器类有一个方法,我想在其中进行服务类 api 调用以及何时存储数据 - 返回它。我尝试自己使用完成处理程序和调度组来处理这个问题,但是(我想我只是遗漏了一些东西)这不起作用。如果您能帮助我解决这个问题,我将不胜感激。提前致谢!

服务等级:

和 Interactor 类(没有完成处理程序或调度组):

补充:我对完成处理程序的尝试

0 投票
0 回答
72 浏览

ios - Swift 并发:使第 3 方库符合参与者隔离

我正在将一些代码库转换为使用 Swift 并发,并且在此过程中遇到了一些障碍。

我正在处理的当前项目有一些它依赖的第 3 方库,在其中一个库中,有一个委托协议,需要从其方法返回一些数据值。

以下是库中委托方法类型的示例:

我试图从协议的实现中返回一些值,如下所示:

如果不做任何修改,上述内容隐式地与 MainActor 隔离,不能满足 FooDelegate 协议的要求。

我尝试过的一种解决方案是使用以下标记功能实现nonisolated

但是这不起作用,因为它引用了视图控制器的视图。这导致view从非隔离的同步上下文中引用。(还有一些其他问题,因为传递到任何委托函数的任何值都需要符合才能Sendable跨参与者传递)。

我的问题是,有没有办法获取第 3 方库并以某种方式对其进行扩展,以使其符合适当的参与者隔离,而无需修改其源代码?

0 投票
0 回答
56 浏览

swift - Swift Actor 的数据竞争问题

我正在将我的代码转换为使用 Swift 并发,我遇到了 Actor 的问题,我不知道如何正确修复它。

这是一个简单的演员:

在我需要更新actor的其他地方,我必须在并发上下文中调用它的函数:

那挺好的。但我不明白的是,如果演员increase像这样将函数作为闭包返回:

在其他地方,我可以获得对返回的闭包的引用并在非并发上下文中自由调用它:

上面的代码将其打印到输出:

我不确定我是否正确理解或使用 Actor。Actor 保护其状态免受数据竞争的影响,但在这种情况下,它不会阻止这种情况。这是正确的行为吗?有没有办法解决它?

0 投票
1 回答
54 浏览

swift - 检索参考列表上的记录(分层记录) - Swift Concurrency & CloudKit

我正在使用 CloudKit(默认的公共数据库)来存储有关两支球队之间比赛的信息。我正在尝试使用带有 async/await 的 Swift Concurrent 方法来检索比赛和团队数据。

比赛被存储为带有一些元数据的“Match” RecordType,比如比赛的年份(“matchYear”)。“比赛”记录类型还包含一个名为“团队”的记录类型的参考列表(每场比赛两个团队)。团队名称存储在“团队”记录类型中(字段“团队名称”)

我的 CloudKit 架构的粗略描述

使用以下代码,我可以从 CloudKit 读取所有“匹配”记录,并将该列表存储到 MatchRecords 数组中,然后我可以使用它来显示匹配列表(使用 SwiftUI,如果这有什么不同的话)。结果数组还包含对每场比赛的球队的引用。

作为此异步功能的一部分,我如何检索团队记录,以便我也将获得可用于列表视图的团队名称?

(我可能首先获取匹配列表,然后遍历该数组并检索每个匹配的详细数据,但这似乎很浪费。我猜应该有一种方法可以将它插入到代码示例中标记的 compactMap 闭包中上面,但是我的 map/reduce 和 async/await 技能让我失望了……)

数据结构可能如下所述。

FWIW我知道因为每场比赛只有两支球队,我也可以将球队名称存储为比赛记录的一部分,但将来我计划还包括每支球队的名单信息,所以我需要来用一种干净且可扩展的方法从 CloudKit 中检索这种类型的分层数据……</p>

在这里,将 CoreData 与 CloudKit 一起使用不是一个选项。

0 投票
1 回答
118 浏览

swift - Swift 5.5 并发:如何序列化异步任务以用 maxConcurrentOperationCount = 1 替换 OperationQueue?

我目前正在迁移我的应用程序以在 Swift 中使用并发模型。我想序列化任务以确保它们一个接一个地执行(没有并行性)。在我的用例中,我想收听 NotificationCenter 发布的通知,并在每次发布新通知时执行一个任务。但我想确保没有以前的任务正在运行。这相当于使用 maxConcurrentOperationCount = 1 的 OperationQueue。

例如,我在我的应用程序中使用 CloudKit 和 Core Data,并使用持久历史跟踪来确定商店中发生了哪些变化。在此将本地商店同步到云示例代码中,Apple 使用操作队列来处理历史处理任务(在 CoreDataStack 中)。此 OperationQueue 的最大操作数设置为 1。

当收到 Core Data 通知时,会向这个串行操作队列中添加一个新任务。因此,如果收到很多通知,它们都会以串行方式一个接一个地执行。

在这个加载和显示大数据馈送示例代码中,Apple 使用任务来处理历史更改(在 QuakesProvider 中)。

我觉得第二个项目有问题,因为任务可以按任何顺序发生,不一定按顺序发生(与 OperationQueue 作为 maxConcurrentOperationCount = 1 的第一个项目相反)。

我们应该在某处使用演员来确保方法被串行调用吗?

我想过这样的实现,但我还不是很满意:

收到新通知时将调用 processRemoteStoreChange 方法(AsyncSequence):

0 投票
3 回答
69 浏览

swift - 如何序列化对类的所有 Void 返回函数的访问(避免竞争条件)?

假设一个类是这样安排的:

如何确保一次只有一个函数处于活动状态,并且每个函数的执行都以 FIFO 方式执行?这将包括Taskin的主体b()。如果Task正在执行,则该类的其他函数都不能进入,它们将排队并在没有交错的情况下操作 FIFO。

由于成员函数可能会在主线程上被调用,因此不应该涉及线程阻塞。

这是我面临的常见情况,我想不出一个合理的解决方案。一开始我很兴奋actor,但是当函数中有一个时,actor允许重新进入await,允许竞争条件。我唯一能找到的就是这里。但是在这里,作者实际上只是将问题进一步推到调用层次结构上。

0 投票
1 回答
43 浏览

alamofire - 将 try await 与上传请求一起使用

我正在使用以下代码进行多部分数据上传

uploadProgress这种情况下,将用作闭包,这有点反对尝试等待。有没有更好的使用方法?

0 投票
2 回答
90 浏览

swift - 如何并行等待任意数量的异步函数

Swift Concurrency 文档提供了以下示例,说明如何并行等待多个异步函数。

有没有办法并行等待任意数量的异步函数?我尝试了下面代码中显示的方法,但找不到使其工作的方法。