#swift
#swift
Вопрос:
В Swift у меня есть рекурсивная функция, которую я хочу, чтобы она выполнялась каждую минуту. Это выглядит примерно так, как показано ниже.
func someFunc() {
// business logics...
DispatchQueue.global().asyncAfter(deadline: .now() 60) {
self.someFunc()
}
}
Дело в том, что это someFunc()
может быть инициировано несколькими вызывающими абонентами, но я хочу разрешить только один экземпляр someFunc(), запущенный или ожидающий выполнения в будущем.
Каков наилучший способ гарантировать, что не более 1 someFunc()
будет запущено или поставлено в очередь в любой момент времени?
(Я использую Swift 5.3)
Ответ №1:
Вы также можете использовать NSLock
для этого:
import PlaygroundSupport
let lock = NSLock()
func someFunc(msg: String) {
guard lock.try() else { return }
print(msg)
DispatchQueue.global().asyncAfter(deadline: .now() 5) {
lock.unlock()
someFunc(msg: msg)
}
}
someFunc(msg: "call1")
someFunc(msg: "call2") // Ignored
someFunc(msg: "call3") // Ignored
PlaygroundPage.current.needsIndefiniteExecution = true
Ответ №2:
Вы можете использовать логическое значение для отслеживания того, что вызов функции находится в очереди (при условии, что вы не вызываете someFunc() из разных потоков)
var isQueued = false
func someFunc() {
if isQueued { return }
// business logics...
isQueued = true
DispatchQueue.global().asyncAfter(deadline: .now() 60) {
self.isQueued = false
self.someFunc()
}
}
Пример
class Example {
var isQueued = false
func someFunc(_ i: Int) {
if isQueued { return }
// business logics...
if i > 500 {
return
}
print(i)
isQueued = true
DispatchQueue.global().asyncAfter(deadline: .now() 1) {
self.isQueued = false
self.someFunc(i * 10)
}
}
}
let t = Example()
t.someFunc(1)
sleep(2)
t.someFunc(2)
sleep(1)
t.someFunc(3)
sleep(1)
t.someFunc(4)
sleep(1)
t.someFunc(5)
С принтами
1
10
100
4
40
400