I have a concurrent function running, that is connected to a UIBarbuttonItem
.init(barButtonSystemItem: .camera, target: self, action: #selector(runClassification(_:))
Although I have run into a weird issue. Running any task (as simple or complex) will not run on the very first initialisation of the view controller. Moving the code outside the Task
runs as expected. Running the function, leaving the view, and tapping the button again will successfully disable the buttons.
Print statements work but any code falls into the void. View Controller isn't constructed any differently than usual.
@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)
}
}
}
-- Update
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")
}