Navaron Bracke
Committed by GitHub

Merge pull request #886 from navaronbracke/fix_ios_torch_crash

fix: Fix ios torch crash
@@ -216,9 +216,12 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -216,9 +216,12 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
216 backgroundQueue.async { 216 backgroundQueue.async {
217 self.captureSession.startRunning() 217 self.captureSession.startRunning()
218 218
219 - // Turn on the flashlight if requested,  
220 - // but after the capture session started. 219 + // After the capture session started, turn on the torch (if requested)
  220 + // and reset the zoom scale back to the default.
  221 + // Ensure that these adjustments are done on the main DispatchQueue,
  222 + // as they interact with the hardware camera.
221 if (torch) { 223 if (torch) {
  224 + DispatchQueue.main.async {
222 do { 225 do {
223 try self.toggleTorch(.on) 226 try self.toggleTorch(.on)
224 } catch { 227 } catch {
@@ -226,15 +229,21 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -226,15 +229,21 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
226 // continue with the capture session anyway. 229 // continue with the capture session anyway.
227 } 230 }
228 } 231 }
  232 + }
229 233
  234 + DispatchQueue.main.async {
230 do { 235 do {
231 try self.resetScale() 236 try self.resetScale()
232 } catch { 237 } catch {
233 // If the zoom scale could not be reset, 238 // If the zoom scale could not be reset,
234 // continue with the capture session anyway. 239 // continue with the capture session anyway.
235 } 240 }
  241 + }
236 242
237 if let device = self.device { 243 if let device = self.device {
  244 + // When querying the dimensions of the camera,
  245 + // stay on the background thread,
  246 + // as this does not change the configuration of the hardware camera.
238 let dimensions = CMVideoFormatDescriptionGetDimensions( 247 let dimensions = CMVideoFormatDescriptionGetDimensions(
239 device.activeFormat.formatDescription) 248 device.activeFormat.formatDescription)
240 let hasTorch = device.hasTorch 249 let hasTorch = device.hasTorch
@@ -277,9 +286,15 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -277,9 +286,15 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
277 device = nil 286 device = nil
278 } 287 }
279 288
280 - /// Toggle the flashlight between on and off. 289 + /// Set the torch mode.
  290 + ///
  291 + /// This method should be called on the main DispatchQueue.
281 func toggleTorch(_ torch: AVCaptureDevice.TorchMode) throws { 292 func toggleTorch(_ torch: AVCaptureDevice.TorchMode) throws {
282 - if (device == nil || !device.hasTorch || !device.isTorchAvailable) { 293 + guard let device = self.device else {
  294 + return
  295 + }
  296 +
  297 + if (!device.hasTorch || !device.isTorchAvailable || !device.isTorchModeSupported(torch)) {
283 return 298 return
284 } 299 }
285 300
@@ -61,6 +61,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -61,6 +61,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
61 start(call, result) 61 start(call, result)
62 case "torch": 62 case "torch":
63 toggleTorch(call, result) 63 toggleTorch(call, result)
  64 + case "setScale":
  65 + setScale(call, result)
  66 + case "resetScale":
  67 + resetScale(call, result)
64 // case "analyze": 68 // case "analyze":
65 // switchAnalyzeMode(call, result) 69 // switchAnalyzeMode(call, result)
66 case "stop": 70 case "stop":
@@ -320,7 +324,11 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -320,7 +324,11 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
320 324
321 // TODO: this method should be removed when iOS and MacOS share their implementation. 325 // TODO: this method should be removed when iOS and MacOS share their implementation.
322 private func toggleTorchInternal(_ torch: AVCaptureDevice.TorchMode) throws { 326 private func toggleTorchInternal(_ torch: AVCaptureDevice.TorchMode) throws {
323 - if (device == nil || !device.hasTorch) { 327 + guard let device = self.device else {
  328 + return
  329 + }
  330 +
  331 + if (!device.hasTorch || !device.isTorchModeSupported(torch)) {
324 return 332 return
325 } 333 }
326 334
@@ -337,7 +345,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -337,7 +345,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
337 } 345 }
338 } 346 }
339 347
340 - func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 348 + /// Reset the zoom scale.
  349 + private func resetScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  350 + // The zoom scale is not yet supported on MacOS.
  351 + result(nil)
  352 + }
  353 +
  354 + /// Set the zoom scale.
  355 + private func setScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  356 + // The zoom scale is not yet supported on MacOS.
  357 + result(nil)
  358 + }
  359 +
  360 + private func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
341 let requestedTorchMode: AVCaptureDevice.TorchMode = call.arguments as! Int == 1 ? .on : .off 361 let requestedTorchMode: AVCaptureDevice.TorchMode = call.arguments as! Int == 1 ? .on : .off
342 362
343 do { 363 do {