How could I turn on the flashlight (torch) during an ARSession?
The standard code, does not work, as as soon the session starts with the flashlight is turned off.
Initializing the ARSession:
let configuration = ARWorldTrackingConfiguration()
self.sceneView.session.run(configuration, options: [.removeExistingAnchors])
Function to turn on/off the flashlight:
private func turnTorch(enabled: Bool) {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else {
return // Cant initiate avcapturedevice error
}
if device.hasTorch {
do {
try device.lockForConfiguration()
if enabled {
device.torchMode = .on
} else {
device.torchMode = .off
}
device.unlockForConfiguration()
} catch {
return //Torch could not be used, lock for configuration failed
}
} else {
return // Torch not available error
}
}
It is because you are trying to turn on the flashlight (torch) some time before your session has run. Using SceneKit, I tried this approach and worked fine for me:
First, add this variable to your class to know when your flashlight (torch) is on or off:
var isTorchOn = false
Next, implement ARSCNViewDelegate
's didRenderScene
method and when the session is ready, turn on the flashlight there. Since this delegate is executed each frame, you need to use isTorchOn
there to run your flashlight method only once.
Also, notice that I've added the isTorchOn
flag inside your turnTorch
method to update its value.
The final and simplified code:
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
var isTorchOn = false
private func turnTorch(enabled: Bool) {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else {
return // Cant initiate avcapturedevice error
}
if device.hasTorch {
do {
try device.lockForConfiguration()
if enabled {
device.torchMode = .on
} else {
device.torchMode = .off
}
self.isTorchOn = enabled // *** Add this line! ***
device.unlockForConfiguration()
} catch {
return
}
} else {
return
}
}
func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
if self.sceneView.session.currentFrame != nil {
if !isTorchOn {
turnTorch(enabled: true)
}
}
}
func sessionWasInterrupted(_ session: ARSession) {
// Probably you would want to turn the torch off here.
}
func sessionInterruptionEnded(_ session: ARSession) {
// Probably you would want to turn the torch on again here.
}
}
You can follow the same approach if you're using SpriteKit.