[英]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.