Torch Strobe not working in light (ambient light) environments on iOS 18.1

As of iOS 18.1 being released we are having issues with our users experiencing issues with our app that relies on strobing the device torch.

We have narrowed this down to being caused on devices with adaptive true-tone flash and have submitted a radar: FB15787160.

The issue seems to be caused by ambient light levels. If run in a dark room, the torch strobes exactly as effectively as in previous iOS versions, if run in a light room, or outdoors, or near a window, the strobe will run for ~1s and then the torch will get stuck on for half a second or so (less frequently it gets stuck off) and then it will strobe again for ~1s and this behaviour repeats indefinitely.

If we go to a darker environment, and background and then foreground the app (this is required) the issue is resolved, until moving to an area with higher ambient light levels again. We have done a lot of debugging, and also discovered that turning off "Auto-Brightness" from Settings -> Accessibility -> Display & Text Size resolves the issue.

We have also viewed logs from Console.app at the time of the issue occurring and it seems to be that there are quite sporadic ambient light level readings at the time at which the issue occurs. The light readings transition from ~100 Lux to ~8000 Lux at the point that the issue starts occurring (seemingly caused by the rear sensor being affected by the torch). With "Auto-Brightness" turned off, it seems these readings stay at lower levels.

This is rendering the primary use case of our app essentially useless, would be great to get to the bottom of it! We can't even really detect it in-app as I believe using SensorKit is restricted to research applications and requires a review process with Apple before accessing?

Edit: It's worth noting this is also affecting other apps with strobe functionality in the exact same way

Just an update on this, another way to fix it is to setup an AVCaptureDeviceInput and AVCaptureVideoDataOutput, attach them to an AVCaptureSession and call startRunning on the session.

Presumably this limits the changes to the torch so it can be used as a camera flash more effectively.

A less than ideal solution, as it will involve hand-holding of users to explain why we require camera permission, and will potentially also be picked up on by the review team too!

A further update after getting some analytics around this into our app:

  • It isn't related to the adaptive true-tone flash, rather it occurs on any device with dual ambient light sensors.
  • We still believe it's only an iOS 18 issue, but may also be present on iOS 18.0.1
  • The issue is not yet resolved on iOS 18.2 beta

Hey @simonmitchell. We are currently dealing with the same issue. did you receive any feedback from Apple yet? I can't seem to open the link to your radar, but I'm not sure if I just don't have access to it.

I have written the following code to gather some data on this issue. It simply flashes the torch at 10 Hz and measures the current time before every torchMode change and usleep call. You can also see that it generates a list of "ideal" timings, which assumes that the torchMode changes are instant and the usleep calls are perfectly accurate. This is obviously not possible, but allows us to calculate the deviation between our hypothetical ideal scenario and the real world.

let device = AVCaptureDevice.default(for: .video)!
try device.lockForConfiguration()

var measurements: [CFTimeInterval] = []

let repeats = 300
let durationMs = 50
let durationUs = UInt32(durationMs * 1000)

var ideal: [CFTimeInterval] = []

for _ in 0..<repeats {
    ideal.append(0.0)
    ideal.append(CFTimeInterval(durationMs))
    ideal.append(0.0)
    ideal.append(CFTimeInterval(durationMs))
}

for i in 0..<repeats {
    measurements.append(CACurrentMediaTime())
    device.torchMode = .on
    measurements.append(CACurrentMediaTime())
    usleep(durationUs)
    measurements.append(CACurrentMediaTime())
    device.torchMode = .off
    measurements.append(CACurrentMediaTime())
    usleep(durationUs)
}

measurements.append(CACurrentMediaTime())

device.unlockForConfiguration()

var diffs: [CFTimeInterval] = []

for (i, timestamp) in measurements[1...].enumerated() {
    let previous = measurements[i]

    diffs.append((timestamp - previous) * 1000 - ideal[i])
}

let str = diffs.map({ String($0) }).joined(separator: "\n")
print(str)

I ran this demo in a dark room on an iPhone 15 Pro Max and iPhone 13 Mini. The measured results can be seen in the graph below. The marked area in red roughly shows the time that the room lights were turned on.

You can clearly see that after turning the ambient light on the iPhone 15 Pro Max regularly takes up to almost 500ms to update the torchMode. The iPhone 13 Mini experiences no such problems. Even after the light is turned off again the iPhone 15 Pro Max continues to miss the desired timings.

I took a video of the demo that you can see here: https://drive.google.com/file/d/1CBWEBWPvq_QF_TLud1-8m1G5guFn_0Qq/view - I sadly cannot make this a proper link, because the Forum seems to block the domain. Uploading the video file itself is also not possible. Here's a screenshot of the setup for good measure:

I was able to reliably and consistently reproduce this issue on an iPhone 15 Pro and iPhone 15 Pro Max. I couldn't get my hands on any iPhone 16 myself yet, but after asking friends to take a slow motion video of a generic strobe app in a bright room it looks like they are not affected.

Hi @hhaceart! I'm so sorry for the delay in replying to this. And apologies you're experiencing the same issue.

Apple originally came back to me and stated it must be something in my code based on the sysdiagnose logs we provided to them, so I then wrapped the setTorchMode call in a measure function:

let continuousClock = ContinuousClock()
let torchTime = continuousClock.measure {
    power == 0 ? device?.torchMode = .off : try? device?.setTorchModeOn(level: power)
}
print("Time to toggle torch with AVCaptureDevice API", torchTime)

and provided them the results from this, clearly showing the same issue you're experiencing. We have just heard back from them to say the issue is resolved on the iOS 18.4 beta, but contrary to that we have heard from users that iOS 18.4 actually makes it worse! I am in the process of installing the developer beta now and will feed back.

Unfortunately this has been made significantly worse in the iOS 18.4 developer beta (Build: 22E5200s). I have updated our feedback, but it seems this has gone entirely the opposite direction than we would have hoped:

The issue now occurs even in dark environments (pitch black in fact) and also occurs even with auto-brightness a11y setting disabled.

This will be absolutely killer for our app if it gets released in its current state!

Hey @simonmitchell, thanks for keeping me up to date, because I didn't receive any response to my feedback yet.

Written by simonmitchell in 827094022
The issue now occurs even in dark environments (pitch black in fact) and also occurs even with auto-brightness a11y setting disabled.

That's pretty bad – at least we could instruct our customers to disable the auto-brightness as a quick workaround so far. But now that that's gone too I honestly don't know what to tell them.

Let's hope that this does not make it in the final release.

Hi @hhaceart absolutely no worries!

I have installed beta 2 this evening and it actually seems to now be resolved as Apple have promised! It’s not daytime here but I’ve tried under the brightest bulb (grow bulb for my lemon tree) I could find, and which previously triggered the issue!

Let’s just hope it remains fixed until GM 👀

Torch Strobe not working in light (ambient light) environments on iOS 18.1
 
 
Q