标签: swift-concurrency

在 Swift 5.5 中,在不支持并发的函数中等待两个任务完成的正确方法是什么?

我有一个应用程序,可以对给定的字符串进行一些处理,这在 2Task秒内完成。在此期间我正在显示动画。当这些Task完成后,我需要隐藏动画。下面的代码可以工作,但看起来不太好。我相信有更好的方法来做到这一点?

let firTask = Task {
    /* Slow-running code */
}

let airportTask = Task {
    /* Even more slow-running code */
}

Task {
    _ = await firTask.result
    _ = await airportTask.result
    
    self.isVerifyingRoute = false
}
Run Code Online (Sandbox Code Playgroud)

task async-await swift swift-concurrency

4
推荐指数
1
解决办法
5932
查看次数

Swift 5.5 并发:创建具有自定义错误类型的任务

我需要在我创建的任务中使用我自己的自定义错误枚举:

enum MyError: Error {
 case someError
}

var myTask: Task<MyModel, MyError> = Task { () throws -> MyModel in
            // in case of an error: 
            // throw .someError
            // ... perform some work
            return MyModel()
        }
Run Code Online (Sandbox Code Playgroud)

但我在任务初始化程序的开头收到以下错误: Referencing initializer 'init(priority:operation:)' on 'Task' requires the types 'MyError' and 'Error' be equivalent

如何限制Task只抛出属于我的自定义错误类型的错误MyError

swift swift5.5 xcode13 swift-concurrency

4
推荐指数
1
解决办法
65
查看次数

Actor 隔离属性无法将“inout”传递给“async”函数调用

我是 Swift 并发的新手(我想像大多数人一样),我遇到了编译器错误,我不知道该怎么办。


struct Thing {
  var counter = 0
  mutating func increment() async {
    counter += 1
  }
}

class Controller: UIViewController {
  var thing = Thing()
  
  func mutate() async {
    await thing.increment()
    print(thing.counter)
  }
}

let c = Controller()
Task {
  await c.mutate()
}
Run Code Online (Sandbox Code Playgroud)

mutate()函数的第一行给出了以下错误。 Actor-isolated property 'thing' cannot be passed 'inout' to 'async' function call

如果我只是继承class而不是UIViewController事情工作正常,但我需要这里的控制器,所以我需要弄清楚如何使其在特定的上下文中工作。

swift swift-concurrency

4
推荐指数
1
解决办法
5851
查看次数

将阻塞函数集成到 Swift async 中

我知道异步 SwiftTask不应该阻塞(异步工作线程必须始终向前推进)。如果我有一个 100% 异步 Swift 应用程序,但需要引入一些阻塞任务,那么正确的方法是什么,不会阻塞任何 swift 异步线程池工作线程?

我假设需要异步线程池之外的新专用线程,如果该假设正确,异步函数等待该线程完成的线程安全方法是什么?我可以使用 的主体withCheckedContinuation来启动线程,将continuation句柄复制到该线程中并continuation.resume在线程完成时从该线程调用吗?

async-await swift swift-concurrency

4
推荐指数
1
解决办法
3550
查看次数

Swift 并发多个等待单个异步结果

AuthorizationRequester可以同时从许多地方调用它,但只有第一个调用可以运行requestAuthorizationFromUser()(并等待几十秒的用户交互) - 其余的这些调用应该await是来自 的结果requestAuthorizationFromUser(),但不能直接调用它。

看代码:

actor AuthorizationRequester {
    enum SimpleResult {
        case success, failure
    }
    
    typealias ResultCompletion = (SimpleResult) -> ()
    
    private var requestInProgress = false
    private var requestCompletions = [ResultCompletion]()
    
    func request(completion: @escaping ResultCompletion) async {
        requestCompletions.append(completion)
        
        guard !requestInProgress else { return }
        
        requestInProgress = true
        
        let result = await requestAuthorizationFromUser()
        
        requestCompletions.forEach { $0(result) }
        requestCompletions.removeAll()
        requestInProgress = false
    }
    
    private func requestAuthorizationFromUser() async -> SimpleResult {
        // ...some code
    } …
Run Code Online (Sandbox Code Playgroud)

swift swift-concurrency

4
推荐指数
1
解决办法
1074
查看次数

在并发执行的代码中引用捕获的 var

我正在快速尝试新的异步/等待模式,但遇到了一些让我感到困惑的事情。

\n
struct ContentView: View {\n    var body: some View  {\n        Text("Hello World!")\n            .task {\n                var num = 1\n\n                Task {\n                    print(num)\n                }\n\n                Task {\n                    print(num)\n                }\n            }\n    }\n\n    func printScore() async {\n        var score = 1\n\n        Task { print(score) }\n        Task { print(score) }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n

有人可以澄清一下上面的屏幕截图,为什么编译器只抱怨捕获的var内部函数,而在使用结构体的计算属性上的修饰符printScore() 执行相同操作时不抱怨(即第 14-24 行)?taskbodyContentView

\n

这是我提出的示例,并对编译器行为感到困惑。我还将编译器设置“严格并发检查\xe2\x80\x9d 构建设置”更改为\xe2\x80\x9cComplete\xe2\x80\x9d,但仍然不这样做没有看到编译器抱怨。

\n

ios async-await swift swiftui swift-concurrency

4
推荐指数
1
解决办法
1451
查看次数

尽管有 @MainActor 注释,但主线程上未触发 UI 更新

我正在注释我的函数,@MainActor以确保可以从任何异步位置安全地调用它以触发 UI 更新。尽管如此,我还是遇到了一个错误,不知何故,UI 更新似乎是在后台线程上尝试的,即使(据我理解)该函数严格绑定到`@MainActor\xc2\xb4.

\n

这是我的代码:

\n
/// Dismisses the popup from its presenting view controller.\n@MainActor public func dismiss() {\n    presentingViewController?.dismiss(self)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它是从 an 内部调用的,NSViewController它使用 监听某个事件NotificationCenter,然后在以下objc函数中启动解雇:

\n
class MainWindowControllerVC: NSWindowController, NSWindowDelegate {\n  override func windowDidLoad() {\n      NotificationCenter.default.addObserver(self, selector: #selector(self.dismissVCastSharePopup), name: .NOTIF_DISMISS_POPUP, object: nil)\n  }\n\n  @objc private func dismissPopup() {\n      // some other cleanup is happening here\n      popup?.dismiss()\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我收到以下错误:

\n
*** Terminating app due to uncaught exception \'NSInternalInconsistencyException\', reason: \'NSWindow drag …
Run Code Online (Sandbox Code Playgroud)

macos appkit actor swift swift-concurrency

4
推荐指数
1
解决办法
882
查看次数

SWIFTUI:从“(IndexSet) async”类型的“async”函数进行的转换无效

我正在学习 SWIFTUI 并尝试制作一些应用程序来测试我的知识,而无需实际遵循教程,因为我喜欢思考为什么事情会以某种方式工作。这就是我学习的方式:)

因此,我尝试调用一个函数来通过 API 发布一些数据。该方法位于 ViewModel 内部。视图是一个列表,我需要能够触发 .OnDelete 修饰符以通过视图模型触发 API 调用。

但我总是面临这样的错误:

从“(IndexSet) async -> Void”类型的“async”函数到同步函数类型“(IndexSet) -> Void”的转换无效

这是代码。

在 ContentView.swift 中:

        // there is a @State var res = PostsViewModel() above the body!
    List { 
        ForEach(res.posts, id:\.self){ item in
            VStack {
                Text(item.title) 
                    .font(.headline)
                Text("\(item.content) <> \(item._id)")
            }
            
        }
        .onDelete{ IndexSet in
                var index: Int = -1
                for idx in IndexSet {
                    index = idx
                }
                print("index ix \(index)")

                 await res.updateData(at: index)
                

        }

    }
Run Code Online (Sandbox Code Playgroud)

在 PostViewModel.swift 中:

    func updateData(at …
Run Code Online (Sandbox Code Playgroud)

swift swiftui swift-concurrency

3
推荐指数
1
解决办法
4138
查看次数

Swift 并发:为什么这个方法是异步的?

我正在尝试思考如何将 Swift 并发性与使用基于块的东西(如 Timer)的旧代码集成。因此,当我构建下面的代码时,编译器告诉我self.handleTimer()该行Expression is 'async' but is not marked with 'await'

为什么是异步的?它没有被标记async并且没有做任何事情。当我在没有计时器的情况下调用它时,我不需要await. 参与者隔离是否意味着对成员的每次调用都是来自该上下文之外的“异步”?

@MainActor
class MyClass {
    
    func startTimer() {
        _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
            Task {
                self.handleTimer() // "Expression is 'async' but is not marked with 'await'"
            }
        }
    }
    
    func handleTimer() {
    }
}
Run Code Online (Sandbox Code Playgroud)

swift swift-concurrency

3
推荐指数
2
解决办法
972
查看次数

PassthroughSubject 的 AsyncPublisher 值属性未生成所有值

我围绕 PassthroughSubject 创建了一个小包装器,将其转换为 AsyncStream。

protocol Channelable {}

final class Channel {
    private let subject = PassthroughSubject<Channelable, Never>()
    
    func send(_ value: Channelable) {
        subject.send(value)
    }
    
    func getValues() -> AsyncStream<Channelable> {
        AsyncStream { continuation in
            let task = Task {
                for await value in subject.values {
                    continuation.yield(value)
                }
            }
            
            continuation.onTermination = { _ in
                task.cancel()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我执行以下操作时:

enum Action: Channelable {
    case execute
}

func test() async {
        let channel = Channel()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            channel.send(Action.execute)
            channel.send(Action.execute) …
Run Code Online (Sandbox Code Playgroud)

swift combine swift-concurrency

3
推荐指数
1
解决办法
773
查看次数

标签 统计

swift ×10

swift-concurrency ×10

async-await ×3

swiftui ×2

actor ×1

appkit ×1

combine ×1

ios ×1

macos ×1

swift5.5 ×1

task ×1

xcode13 ×1