Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不中断主线程的情况下延迟swift中的for循环?_Swift_Iphone_Flashlight - Fatal编程技术网

如何在不中断主线程的情况下延迟swift中的for循环?

如何在不中断主线程的情况下延迟swift中的for循环?,swift,iphone,flashlight,Swift,Iphone,Flashlight,我正在尝试一次延迟读取一个字符串一个字符。在进入下一个字符前1秒 我曾尝试在for循环中实现delay函数,但它有两个问题。 1.延迟不一致,在字符之间移动时所用的时间也不相同。 2.它破坏了主线程,我认为这是导致相机视图冻结的原因。然而,我认为也有可能在相机打开时激活手电筒会冻结信号,从而导致故障 func delay(_ delay:Double, closure:@escaping ()->()) { DispatchQueue.main.asyncAfter(

我正在尝试一次延迟读取一个字符串一个字符。在进入下一个字符前1秒

我曾尝试在for循环中实现delay函数,但它有两个问题。 1.延迟不一致,在字符之间移动时所用的时间也不相同。 2.它破坏了主线程,我认为这是导致相机视图冻结的原因。然而,我认为也有可能在相机打开时激活手电筒会冻结信号,从而导致故障

func delay(_ delay:Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now () + Double(Int64(delay * 
    Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: 
    closure)
}

func scriptReader(){
    let str = "10101000001111110000110"
    for i in 0..<str.count {

        delay(Double(i) * 0.5) { 
            let index = str.index(str.startIndex, offsetBy:  i) 
            self.flash(number: str[index]) 
        }
    }
}
func flash(number: Character){
    guard let device = AVCaptureDevice.default(for: 
 AVMediaType.video) else { return }
    guard device.hasTorch else { return }

    if number == "0" {
        print("off")
        do {
            try device.lockForConfiguration()

            if (device.torchMode == AVCaptureDevice.TorchMode.on) {
                device.torchMode = AVCaptureDevice.TorchMode.off
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }

    if number == "1"{
        print("on")
        do {
            try device.lockForConfiguration()

            if (device.torchMode == AVCaptureDevice.TorchMode.off) {
                do {
                    try device.setTorchModeOn(level: 1.0)
                } catch {
                    print(error)
                }
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }
}
func-delay(delay:Double,closure:@escaping()->()){
DispatchQueue.main.asyncAfter(
截止日期:DispatchTime.now()+双倍(Int64)(延迟*
Double(每秒NSEC\u))/Double(每秒NSEC\u),执行:
(关闭)
}
func脚本读取器(){
让str=“1010100000111110000110”

对于0中的i..我认为摄影机冻结是因为您每次在for循环中调用其属性,执行一次,将其属性传递到func中获取

尝试此代码来修复您的故障

    func scriptReader(){
    let str = "10101000001111110000110"
    guard let device = AVCaptureDevice.default(for: .video) else { return }
    guard device.hasTorch else { return }
    for i in 0..<str.count {
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.5) {
            let index = str.index(str.startIndex, offsetBy:  i)
            self.flash(number: str[index])
        }
    }
}

func flash(device: AVCaptureDevice, isOn: Bool) {
    do {
        try device.lockForConfiguration()
        device.torchMode = isOn ? AVCaptureDevice.TorchMode.off : device.setTorchModeOn(level: 1.0)
        device.unlockForConfiguration()
    } catch {
        print(error)
    }
}
func脚本读取器(){
让str=“1010100000111110000110”
guard let device=AVCaptureDevice.default(对于:。视频)else{return}
guard device.hasTorch else{return}

对于0中的i..我认为摄影机冻结是因为您每次在for循环中调用其属性,执行一次,将其属性传递到func中获取

尝试此代码来修复您的故障

    func scriptReader(){
    let str = "10101000001111110000110"
    guard let device = AVCaptureDevice.default(for: .video) else { return }
    guard device.hasTorch else { return }
    for i in 0..<str.count {
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.5) {
            let index = str.index(str.startIndex, offsetBy:  i)
            self.flash(number: str[index])
        }
    }
}

func flash(device: AVCaptureDevice, isOn: Bool) {
    do {
        try device.lockForConfiguration()
        device.torchMode = isOn ? AVCaptureDevice.TorchMode.off : device.setTorchModeOn(level: 1.0)
        device.unlockForConfiguration()
    } catch {
        print(error)
    }
}
func脚本读取器(){
让str=“1010100000111110000110”
guard let device=AVCaptureDevice.default(对于:。视频)else{return}
guard device.hasTorch else{return}

对于i in 0.Re您首先关心的问题是,使用一系列的
asyncAfter
将受到“计时器合并”的影响,在这种情况下,操作系统将对未来的、单独安排的计时器进行分组,一次触发所有计时器,以充分利用设备电池(操作系统唤醒设备的频率越低,电池寿命越好).定时计时器越远,操作系统的整合就越有效

使用重复的
计时器可以避免这种情况:

func handle(string: String) {
    guard !string.isEmpty else { return }

    var index = string.startIndex
    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
        if string[index] == "0" {
            // handle "0"
        } else {
            // handle not "0"
        }

        index = string.index(after: index)
        if index == string.endIndex  { timer.invalidate() }
    }
}

首先,使用一系列的
asyncAfter
会受到“计时器合并”的影响,操作系统会将未来的、单独安排的计时器分组,一次触发所有计时器,以充分利用设备电池(操作系统唤醒设备的频率越低,电池寿命越好).定时计时器越远,操作系统的整合就越有效

使用重复的
计时器可以避免这种情况:

func handle(string: String) {
    guard !string.isEmpty else { return }

    var index = string.startIndex
    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
        if string[index] == "0" {
            // handle "0"
        } else {
            // handle not "0"
        }

        index = string.index(after: index)
        if index == string.endIndex  { timer.invalidate() }
    }
}

像这样简单的方法也可能奏效:

let threadName = "FlashThread"
let string = "10101000001111110000110"

//Create a custom thread
DispatchQueue(label: threadName).async {
    print("Thread Start")

    //Start loop
    string.forEach { (c) in
        print(c)

        //Do something on main thread
        DispatchQueue.main.async {
            self.flash(number: c)
        }

        //Put your thread to sleep for a second
        sleep(1)
    }

    print("Thread END")
}

像这样简单的方法也可能奏效:

let threadName = "FlashThread"
let string = "10101000001111110000110"

//Create a custom thread
DispatchQueue(label: threadName).async {
    print("Thread Start")

    //Start loop
    string.forEach { (c) in
        print(c)

        //Do something on main thread
        DispatchQueue.main.async {
            self.flash(number: c)
        }

        //Put your thread to sleep for a second
        sleep(1)
    }

    print("Thread END")
}

我现在已经解决了这个问题。第一个问题是由Rob提供的计时器代码解决的。这停止了主线程的冻结,现在代码以一致的时间间隔在字符串中迭代。 第二个问题是通过消除
AVCaptureDevice
的多个实例来解决的,一旦解决了这个问题,代码就会正常工作。
感谢您的帮助!

我现在已经解决了这个问题。第一个问题是通过Rob提供的计时器代码解决的。这停止了主线程的冻结,现在代码在两个线程之间以一致的时间遍历字符串。 第二个问题是通过消除
AVCaptureDevice
的多个实例来解决的,一旦解决了这个问题,代码就会正常工作。
感谢您的帮助!

感谢您的回复,我对您的解决方案进行了一些修改,但仍然存在故障问题。flash方法有一些我需要的逻辑,所以我保留了它,我不完全确定isOn变量的重要性。有人知道是否可以在没有cau的情况下控制闪光灯吗出现故障?冻结仅在手电筒打开时发生。
func scriptReader(){let str=“1010100000111110000110”guard let device=AVCaptureDevice.default(对于:。视频)else{return}guard device.hasTorch else{return}对于0中的i..感谢您的回复,我对您的解决方案进行了一些修改,但仍然存在小故障问题。flash方法有一些我需要的逻辑,因此我保留了它,我不完全确定isOn变量的重要性。有人知道是否有可能在没有原因的情况下控制闪光灯吗g故障?只有当手电筒打开时才会发生冻结。
func scriptReader(){let str=“1010100000111110000110”guard let device=AVCaptureDevice.default(对于:。视频)else{return}guard device.hasTorch else{return}对于0中的我…非常感谢,这修复了时间间隔的问题。我仍然存在一个问题,即当闪光灯打开相机馈送时,相机馈送停止工作。您知道在相机馈送处于活动状态时是否可以操作闪光灯吗?有趣的是,闪光灯不会停止我朋友手机上的相机(iPhone 7)但它在我的(iPhone X)上不起作用。再次感谢您的帮助!@I.Winson-“您知道在相机馈送处于活动状态时是否可以操作手电筒吗?”…您是否在代码的其他地方执行任何
lockForConfiguration
?isInUseByAnotherApplication
isSuspended
返回的值是什么?非常感谢,这解决了时间间隔的问题。我仍然有一个问题,当闪光灯打开相机馈送时,相机馈送停止工作。您知道吗如果可以在相机馈送处于活动状态时操作手电筒?有趣的是,手电筒不会停止我朋友手机(iPhone 7)上的相机,但在我的手机(iPhone X)上不工作。再次感谢您的帮助!@I.Winson-“您知道在相机馈送处于活动状态时是否可以操作手电筒吗?”…您是否在代码的其他地方执行任何
锁定配置