[英]Swift concurrency failing on first load
我有一个并发函数正在运行,它连接到UIBarbuttonItem
.init(barButtonSystemItem: .camera, target: self, action: #selector(runClassification(_:))
虽然我遇到了一个奇怪的问题。 运行任何任务(无论是简单的还是复杂的)都不会在视图控制器的第一次初始化时运行。 将代码移到Task
之外按预期运行。 运行函数,离开视图,再次点击按钮将成功禁用按钮。
打印语句有效,但任何代码都落入了空白。 View Controller 的构造与平常没有任何不同。
@objc func runClassification(_ sender: UIBarButtonItem) {
Task {
// This runs
navigationItem.rightBarButtonItems?.forEach { $0.isEnabled = false }
guard let image = imageView.image else { return }
do {
let response = try await MLClassifer.sharedManager.updateClassifications(capturedImage: image)
// None of this runs on first call.
print("MLClassifer.sharedManager.updateClassifications begining")
} catch {
debugPrint(error)
}
}
}
-- 更新MLClassifier.swift
private typealias ClassifierCheckedContinuation = CheckedContinuation<[VNRecognizedObjectObservation], Error> // 1
private var classifierContinuation: ClassifierCheckedContinuation?
@MainActor
func updateClassifications(capturedImage: UIImage) async throws -> [VNRecognizedObjectObservation] {
self.capturedImage = capturedImage
let orientation = CGImagePropertyOrientation(capturedImage.imageOrientation)
guard let ciImage = CIImage(image: capturedImage) else {
throw MLClassiferError.invalidConversion
}
guard let model = self.model else {
throw MLClassiferError.invalidModel
}
let mlModel = try VNCoreMLModel(for: model)
let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation)
let request = VNCoreMLRequest(model: mlModel) { request, error in
self.processClassifications(for: request, error: error)
}
try handler.perform([request])
return try await withCheckedThrowingContinuation { (continuation: ClassifierCheckedContinuation) in
self.classifierContinuation = continuation
}
}
func processClassifications(for request: VNRequest, error: Error?) {
if let error = error {
classifierContinuation?.resume(throwing: error)
return
}
guard let results = request.results, !results.isEmpty else {
classifierContinuation?.resume(throwing: MLClassiferError.invalidConversion)
return
}
guard let classifications = results as? [VNRecognizedObjectObservation], !classifications.isEmpty else {
classifierContinuation?.resume(throwing: MLClassiferError.invalidConversion)
return
}
guard let image = self.capturedImage,
let capturedImage = CIImage(image: image)
else {
classifierContinuation?.resume(throwing: MLClassiferError.invalidConversion)
return
}
classifierContinuation?.resume(returning: classifications)
print("MLClassifer.sharedManager.updateClassifications returning")
}
经过几个半睡不醒的夜晚,我找到了解决办法。
而不是这样;
let request = VNCoreMLRequest(model: mlModel) { request, error in
self.processClassifications(for: request, error: error)
}
try handler.perform([request])
return try await withCheckedThrowingContinuation { (continuation: ClassifierCheckedContinuation) in
self.classifierContinuation = continuation
}
你需要这样:在闭包内抛出handler.perform
似乎是缺少的难题。
return try await withCheckedThrowingContinuation { continuation in
self.classifierContinuation = continuation
let request = VNCoreMLRequest(model: mlModel) { request, error in
self.processClassifications(for: request, error: error)
}
try? handler.perform([request])
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.