Skip to content

Commit

Permalink
Merge pull request #8 from jhoogstraat/fix-ios-force-unwrap
Browse files Browse the repository at this point in the history
Catch more errors on iOS
  • Loading branch information
jhoogstraat authored Jun 23, 2021
2 parents 19689a3 + f6f138d commit 9879753
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 38 deletions.
74 changes: 49 additions & 25 deletions fast_barcode_scanner/ios/Classes/BarcodeReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum ReaderError: Error {
case noInputDevice
case cameraNotSuitable(Resolution, Framerate)
case unauthorized
case configurationLockError(Error)
}

enum Resolution: String {
Expand Down Expand Up @@ -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,
Expand All @@ -111,7 +112,7 @@ class BarcodeReader: NSObject {
guard captureDevice != nil else {
throw ReaderError.noInputDevice
}

do {
let input = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(input)
Expand All @@ -121,8 +122,7 @@ class BarcodeReader: NSObject {
}
throw error
}



captureSession.addOutput(dataOutput)
captureSession.addOutput(metadataOutput)

Expand All @@ -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
Expand All @@ -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
}

Expand All @@ -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)
}
}

Expand Down
31 changes: 18 additions & 13 deletions fast_barcode_scanner/ios/Classes/FastBarcodeScannerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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,
Expand Down Expand Up @@ -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)
}

Expand Down

0 comments on commit 9879753

Please sign in to comment.