From f6f138d8e1c01d265946937bb611e237d6657bca Mon Sep 17 00:00:00 2001 From: Joshua Hoogstraat <34964599+jhoogstraat@users.noreply.github.com> Date: Sat, 19 Jun 2021 14:22:25 +0200 Subject: [PATCH] catch more errors on ios --- .../ios/Classes/BarcodeReader.swift | 74 ++++++++++++------- .../Classes/FastBarcodeScannerPlugin.swift | 31 ++++---- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/fast_barcode_scanner/ios/Classes/BarcodeReader.swift b/fast_barcode_scanner/ios/Classes/BarcodeReader.swift index 62b67872..0494307a 100644 --- a/fast_barcode_scanner/ios/Classes/BarcodeReader.swift +++ b/fast_barcode_scanner/ios/Classes/BarcodeReader.swift @@ -38,6 +38,7 @@ enum ReaderError: Error { case noInputDevice case cameraNotSuitable(Resolution, Framerate) case unauthorized + case configurationLockError(Error) } enum Resolution: String { @@ -87,11 +88,11 @@ class BarcodeReader: NSObject { var captureDevice: AVCaptureDevice! var captureSession: AVCaptureSession let dataOutput: AVCaptureVideoDataOutput - let metadataOutput: AVCaptureMetadataOutput + var metadataOutput: AVCaptureMetadataOutput let codeCallback: ([String]) -> Void let detectionMode: DetectionMode let position: AVCaptureDevice.Position - var torchActiveBeforeStop = false + var torchActiveOnStop = false var previewSize: CMVideoDimensions! init(textureRegistry: FlutterTextureRegistry, @@ -111,7 +112,7 @@ class BarcodeReader: NSObject { guard captureDevice != nil else { throw ReaderError.noInputDevice } - + do { let input = try AVCaptureDeviceInput(device: captureDevice) captureSession.addInput(input) @@ -121,8 +122,7 @@ class BarcodeReader: NSObject { } throw error } - - + captureSession.addOutput(dataOutput) captureSession.addOutput(metadataOutput) @@ -146,34 +146,46 @@ class BarcodeReader: NSObject { throw ReaderError.cameraNotSuitable(arguments.resolution, arguments.framerate) } - // swiftlint:disable:next force_try - try! captureDevice.lockForConfiguration() - captureDevice.activeFormat = optimalFormat - captureDevice.activeVideoMinFrameDuration = optimalFormat.videoSupportedFrameRateRanges.first!.minFrameDuration - captureDevice.activeVideoMaxFrameDuration = optimalFormat.videoSupportedFrameRateRanges.first!.minFrameDuration - captureDevice.unlockForConfiguration() + do { + try captureDevice.lockForConfiguration() + captureDevice.activeFormat = optimalFormat + captureDevice.activeVideoMinFrameDuration = + optimalFormat.videoSupportedFrameRateRanges.first!.minFrameDuration + captureDevice.activeVideoMaxFrameDuration = + optimalFormat.videoSupportedFrameRateRanges.first!.minFrameDuration + captureDevice.unlockForConfiguration() + } catch { + throw ReaderError.configurationLockError(error) + } previewSize = CMVideoFormatDescriptionGetDimensions(captureDevice.activeFormat.formatDescription) } - func start(fromPause: Bool) { + func start(fromPause: Bool) throws { + guard captureDevice != nil else { return } + captureSession.startRunning() if !fromPause { self.textureId = textureRegistry.register(self) } - if torchActiveBeforeStop { - // swiftlint:disable:next force_try - try! captureDevice.lockForConfiguration() - captureDevice.torchMode = .on - captureDevice.unlockForConfiguration() - torchActiveBeforeStop = false + if (torchActiveOnStop) { + do { + try captureDevice.lockForConfiguration() + captureDevice.torchMode = .on + captureDevice.unlockForConfiguration() + torchActiveOnStop = false + } catch { + throw ReaderError.configurationLockError(error) + } } } func stop(pause: Bool) { - torchActiveBeforeStop = captureDevice.isTorchActive + guard captureDevice != nil else { return } + + torchActiveOnStop = captureDevice.isTorchActive captureSession.stopRunning() if !pause { pixelBuffer = nil @@ -183,10 +195,16 @@ class BarcodeReader: NSObject { } func toggleTorch() -> Bool { - // swiftlint:disable:next force_try - try! captureDevice.lockForConfiguration() - captureDevice.torchMode = captureDevice.isTorchActive ? .off : .on - captureDevice.unlockForConfiguration() + guard captureDevice != nil && captureDevice.isTorchAvailable else { return false } + + do { + try captureDevice.lockForConfiguration() + captureDevice.torchMode = captureDevice.isTorchActive ? .off : .on + captureDevice.unlockForConfiguration() } catch { + print(error) + return false + } + return captureDevice.isTorchActive } @@ -200,13 +218,19 @@ class BarcodeReader: NSObject { } } - func resume() { + func resume() throws { switch detectionMode { case .continuous: return case .pauseDetection: + guard !captureSession.outputs.contains(metadataOutput) else { return } + + let types = metadataOutput.metadataObjectTypes + metadataOutput = AVCaptureMetadataOutput() + metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.global(qos: .default)) + metadataOutput.metadataObjectTypes = types captureSession.addOutput(metadataOutput) case .pauseVideo: - start(fromPause: true) + try start(fromPause: true) } } diff --git a/fast_barcode_scanner/ios/Classes/FastBarcodeScannerPlugin.swift b/fast_barcode_scanner/ios/Classes/FastBarcodeScannerPlugin.swift index 6ae21f33..b23edc04 100644 --- a/fast_barcode_scanner/ios/Classes/FastBarcodeScannerPlugin.swift +++ b/fast_barcode_scanner/ios/Classes/FastBarcodeScannerPlugin.swift @@ -48,22 +48,27 @@ public class FastBarcodeScannerPlugin: NSObject, FlutterPlugin { } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "start": start(call: call, result: result) - case "stop": stop(result: result) - case "pause": pause(result: result) - case "resume": resume(result: result) - case "toggleTorch": toggleTorch(result: result) - case "heartBeat": result(nil) - default: result(FlutterMethodNotImplemented) - } + do { + switch call.method { + case "start": start(call: call, result: result) + case "stop": stop(result: result) + case "pause": pause(result: result) + case "resume": try resume(result: result) + case "toggleTorch": toggleTorch(result: result) + case "heartBeat": result(nil) + default: result(FlutterMethodNotImplemented) + } + } catch { + print(error) + result(FlutterError(code: "THROW", message: "\(error)", details: nil)) + } } func start(call: FlutterMethodCall, result: @escaping FlutterResult) { guard reader == nil else { let error = FlutterError(code: "ALREADY_RUNNING", message: "Start cannot be called when already running", - details: "") + details: nil) result(error) return } @@ -81,7 +86,7 @@ public class FastBarcodeScannerPlugin: NSObject, FlutterPlugin { self.channel.invokeMethod("read", arguments: code) } - reader!.start(fromPause: false) + try reader!.start(fromPause: false) result([ "surfaceWidth": reader!.previewSize.height, @@ -117,8 +122,8 @@ public class FastBarcodeScannerPlugin: NSObject, FlutterPlugin { result(nil) } - func resume(result: @escaping FlutterResult) { - reader?.resume() + func resume(result: @escaping FlutterResult) throws { + try reader?.resume() result(nil) }