如何在不中断主线程的情况下延迟swift中的for循环?
我正在尝试一次延迟读取一个字符串一个字符。在进入下一个字符前1秒 我曾尝试在for循环中实现delay函数,但它有两个问题。 1.延迟不一致,在字符之间移动时所用的时间也不相同。 2.它破坏了主线程,我认为这是导致相机视图冻结的原因。然而,我认为也有可能在相机打开时激活手电筒会冻结信号,从而导致故障如何在不中断主线程的情况下延迟swift中的for循环?,swift,iphone,flashlight,Swift,Iphone,Flashlight,我正在尝试一次延迟读取一个字符串一个字符。在进入下一个字符前1秒 我曾尝试在for循环中实现delay函数,但它有两个问题。 1.延迟不一致,在字符之间移动时所用的时间也不相同。 2.它破坏了主线程,我认为这是导致相机视图冻结的原因。然而,我认为也有可能在相机打开时激活手电筒会冻结信号,从而导致故障 func delay(_ delay:Double, closure:@escaping ()->()) { DispatchQueue.main.asyncAfter(
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-“您知道在相机馈送处于活动状态时是否可以操作手电筒吗?”…您是否在代码的其他地方执行任何锁定配置
?