我需要取消所有嵌套任务我尝试取消其父级但没有任何反应所有嵌套任务继续运行。
private var observationTask: Task<Void, Never>?
...
observationTask = Task {
Task {
for await users in list.$users.values {
updateTableView(withUsers: users)
}
}
Task {
for await users in list.$users.values {
updateTableView(withUsers: users)
}
}
}
....
observationTask.cancel()
Run Code Online (Sandbox Code Playgroud)
}
我有一个基于回调的 API。
func start(_ completion: @escaping () -> Void)
Run Code Online (Sandbox Code Playgroud)
我想在该 API 之上编写一个 async/await 包装器,将实现推迟到基于原始回调的 API。
func start() async {
let task = Task()
start {
task.fulfill()
}
return await task
}
Run Code Online (Sandbox Code Playgroud)
显然,这段代码没有连接 - 它不是真实的,. 上没有fulfill方法Task。
问题:有没有办法在 Swift 中使用非结构化并发来帮助我实现这一目标?
Task当在无任务上下文中创建(例如,从一些随机AppKit代码)时,创建分离任务或常规任务之间有区别吗?例如,调用
Task.detachedTask.init由于该任务没有可继承的参与者,我认为这两个调用必须是等效的,或者是否仍然需要考虑实现差异?
我想单击 SwiftUI 中的一个按钮来触发 JSON 编码操作。此操作非常耗时,因此我需要它是异步的。我已经尝试了两种解决方案,但它们不起作用。一个主要问题是如何创建异步版本的 json 编码?
\n解决方案1)
\npublic func encodeJSON<T>(_ value: T, encoder: JSONEncoder, completionHandler: @escaping (Data?, Error?) -> Void) where T: Encodable {\n DispatchQueue.global().async {\n do {\n let data = try encoder.encode(value)\n DispatchQueue.main.async {\n completionHandler(data, nil)\n print("finish encode json")\n }\n } catch {\n DispatchQueue.main.async {\n completionHandler(nil, error)\n print("fail encode json")\n }\n }\n }\n }\n \n public func encodeJSON<T>(_ value: T, encoder: JSONEncoder) async throws -> Data where T: Encodable {\n \n try await withUnsafeThrowingContinuation { continuation …Run Code Online (Sandbox Code Playgroud) 考虑以下相对简单的 Swift 程序:
import Foundation
func printContext(function: String = #function, line: Int = #line) {
print("At \(function):\(line): Running on \(Thread.current) (main: \(Thread.isMainThread))")
}
printContext()
Task { @MainActor in
printContext()
}
Task.detached { @MainActor in
printContext()
}
Task {
await MainActor.run {
printContext()
}
}
DispatchQueue.main.async {
printContext()
}
dispatchMain()
Run Code Online (Sandbox Code Playgroud)
根据全球参与者的建议,我预计DispatchQueue.main.async { ...大致相当于Task.detached { @MainActor in ...。
然而,在 Swift 5.6.1 上arm64-apple-macosx12.0,该程序似乎在调用时不确定地产生不同的结果。有时我会得到预期的输出:
At main:7: Running on <_NSMainThread: 0x600000083c80>{number = 1, name = main} (main: …Run Code Online (Sandbox Code Playgroud) 如何向需要与 MainActor 隔离的类添加 Codable 一致性?
例如,以下代码会给出编译器错误:
@MainActor final class MyClass: Codable {
var value: Int
enum CodingKeys: String, CodingKey {
case value
}
init(from decoder: Decoder) throws { // <-- Compiler error: Initializer 'init(from:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Decodable'
let data = try decoder.container(keyedBy: CodingKeys.self)
self.value = try data.decode(Int.self, forKey: .value)
}
func encode(to encoder: Encoder) throws { // <-- Compiler error: Instance method 'encode(to:)' isolated to global actor 'MainActor' can not …Run Code Online (Sandbox Code Playgroud) 在这种情况下,异步函数读取文件并返回解析的内容。
在我看来,我想从主线程加载内容,然后在完成后更新视图。
我在不同的地方使用过这种模式,并注意到在某些情况下,异步调用是在主线程上(通过调试),而在其他情况下,它是在线程Thread 4 Queue : com.apple.root.user-initiated-qos.cooperative (concurrent)上
例如:
struct MyView: View {
@State var data = "some data"
var body: some View {
Button("refresh") {
// when the button is pressed refresh it
Task {
await refresh()
}
}.task {
// when the view appears
await refresh()
}
Text("the data is \(data)") // write the data which was refreshed async
}
}
func refresh() async {
do {
let res = try await anotherAyncFunction()
data = res …Run Code Online (Sandbox Code Playgroud) 我正在监听发布者的更改,然后在管道中异步获取一些数据并使用结果更新视图。但是,我不确定如何使其可测试。我怎样才能最好地等到期望得到满足?
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
NavigationView {
List(viewModel.results, id: \.self) {
Text($0)
}
.searchable(text: $viewModel.searchText)
}
}
}
Run Code Online (Sandbox Code Playgroud)
final class ContentViewModel: ObservableObject {
@Published var searchText: String = ""
@Published var results: [String] = []
private var cancellables = Set<AnyCancellable>()
init() {
observeSearchText()
}
func observeSearchText() {
$searchText
.dropFirst()
.debounce(for: 0.8, scheduler: DispatchQueue.main)
.sink { _ in
Task {
await self.fetchResults()
}
}.store(in: &cancellables)
}
private func fetchResults() …Run Code Online (Sandbox Code Playgroud) 接受的答案没有直接回答原来的问题,但帮助解决了我试图解决的根本问题:我想将 AsyncStream (这是一个 AsyncSequence)映射到另一个元素类型为 T2 的 AsyncSequence 中。我在此评论中添加了一些细节。
\n我想将 an 映射AsyncStream到另一个AsyncStream。我想知道是否有一个.map可以像数组一样使用的。
引用苹果文档:
\n\n\n创建一个异步序列,将给定的闭包映射到异步序列\xe2\x80\x99s 元素上。
\n
下面的代码有错误:
\nCannot convert value of type \'AsyncMapSequence<AsyncStream<Int>, Int>\' to specified type \'AsyncStream<Int>\'\nRun Code Online (Sandbox Code Playgroud)\n.map据我了解,这是因为在这种情况下的返回类型是AsyncMapSequence<...>而不是AsyncStream<Int>。
有没有一种方法可以使用转换函数将 an 映射AsyncStream<T1>到 an ,就像映射到一样?AsyncStream<T2>T1 \xe2\x86\x92 T2Array<T1>Array<T2>
先感谢您!
\nCannot convert value of type \'AsyncMapSequence<AsyncStream<Int>, Int>\' to specified …Run Code Online (Sandbox Code Playgroud) 在使用 Swift 5.x 和 Xcode 14 构建的 Mac 应用程序中,我有一个控制器对象。该对象具有@PublishedSwiftUI 视图观察到的多个属性,因此我将该对象放置在@MainActor这样的位置:
@MainActor
final class AppController: NSObject, ObservableObject
{
@Published private(set) var foo: String = ""
@Published private(set) var bar: Int = 0
private func doStuff() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
当Mac进入睡眠状态时,这个应用程序需要采取某些操作,因此我在方法中订阅了适当的通知init(),但由于AppController用 装饰@MainActor,我收到此警告:
override init()
{
NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.willSleepNotification, object: nil, queue: .main) { [weak self] note in
self?.doStuff() // "Call to main actor-isolated instance method 'doStuff()' in a synchronous nonisolated context; …Run Code Online (Sandbox Code Playgroud) swift ×9
swiftui ×4
async-await ×3
concurrency ×2
actor ×1
appkit ×1
asynchronous ×1
button ×1
combine ×1
swift5 ×1