You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS开发:如何实现iPhone设置开关开启时闪光灯闪烁1秒?

嗨,我来帮你搞定这个闪光灯提示闪烁的问题~

首先得说下你之前踩的两个坑:

  • UIView.animate完全不对路,这个API是专门用来做视图属性(比如位置、透明度)动画的,它根本不会帮你把“打开闪光灯”这个操作拉长1秒执行,而是立刻执行动画块里的代码,然后马上触发completion回调,所以闪烁时长自然不对。
  • Thread.sleep确实是糟糕的实践,它会直接阻塞主线程,导致你的设置页面完全卡住,用户体验极差。

最优解决方案:用DispatchQueue实现非阻塞延迟

正确的思路是:先打开闪光灯,然后延迟1秒后再关闭,而且这个延迟不能阻塞主线程。DispatchQueue.main.asyncAfter就是干这个的完美工具,它能精确控制延迟时间,同时不会影响UI响应。

基础版代码

// 用户开启开关时,调用这个方法触发提示闪烁
func triggerFlashOnHint() {
    // 立刻打开闪光灯
    ViewController.toggleFlash(on: true)
    
    // 延迟1秒后关闭闪光灯
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        ViewController.toggleFlash(on: false)
    }
}

进阶版:处理重复切换的情况

如果用户在1秒内反复切换开关,上面的基础版可能会出现逻辑混乱(比如之前的关闭操作还在等待执行,新的打开操作又触发了)。可以用DispatchWorkItem来管理延迟任务,支持取消之前的任务:

// 用来保存待执行的关闭闪光灯任务
private var flashOffWorkItem: DispatchWorkItem?

func triggerFlashOnHint() {
    // 先取消之前未执行的关闭任务(如果有的话)
    flashOffWorkItem?.cancel()
    
    // 打开闪光灯
    ViewController.toggleFlash(on: true)
    
    // 创建新的关闭任务
    let workItem = DispatchWorkItem { [weak self] in
        ViewController.toggleFlash(on: false)
        self?.flashOffWorkItem = nil
    }
    flashOffWorkItem = workItem
    
    // 延迟1秒执行关闭
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: workItem)
}

额外注意点

确保你的toggleFlash方法是线程安全的,因为AVCaptureDevice的操作建议在串行队列中执行(比如你用来管理相机会话的队列),如果之前的实现是在主线程操作的,那上面的代码没问题;如果是在后台队列,记得把DispatchQueue.main换成你对应的串行队列。

内容的提问来源于stack exchange,提问作者Denys Triasunov

火山引擎 最新活动