Navaron Bracke
Committed by GitHub

Merge pull request #886 from navaronbracke/fix_ios_torch_crash

fix: Fix ios torch crash
@@ -215,26 +215,35 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -215,26 +215,35 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
215 215
216 backgroundQueue.async { 216 backgroundQueue.async {
217 self.captureSession.startRunning() 217 self.captureSession.startRunning()
218 -  
219 - // Turn on the flashlight if requested,  
220 - // but after the capture session started. 218 +
  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 {
  225 + do {
  226 + try self.toggleTorch(.on)
  227 + } catch {
  228 + // If the torch does not turn on,
  229 + // continue with the capture session anyway.
  230 + }
  231 + }
  232 + }
  233 +
  234 + DispatchQueue.main.async {
222 do { 235 do {
223 - try self.toggleTorch(.on) 236 + try self.resetScale()
224 } catch { 237 } catch {
225 - // If the torch does not turn on, 238 + // If the zoom scale could not be reset,
226 // continue with the capture session anyway. 239 // continue with the capture session anyway.
227 } 240 }
228 } 241 }
229 242
230 - do {  
231 - try self.resetScale()  
232 - } catch {  
233 - // If the zoom scale could not be reset,  
234 - // continue with the capture session anyway.  
235 - }  
236 -  
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,12 +286,18 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -277,12 +286,18 @@ 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 {
283 return 294 return
284 } 295 }
285 - 296 +
  297 + if (!device.hasTorch || !device.isTorchAvailable || !device.isTorchModeSupported(torch)) {
  298 + return
  299 + }
  300 +
286 if (device.torchMode != torch) { 301 if (device.torchMode != torch) {
287 try device.lockForConfiguration() 302 try device.lockForConfiguration()
288 device.torchMode = torch 303 device.torchMode = torch
@@ -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 {