在 swift 中进行轮询的正确方法?
Proper way to do polling in swift?
我对其他编程语言有很多经验,但在swift 方面没有那么多 3. 我想做轮询循环。这是我写的:
DispatchQueue.global(qos: .userInitiated).async {
[unowned self] in
while self.isRunning {
WebService.getPeople(completion: nil)
sleep(100)
}
}
这对我来说很好,每 100 秒,我进行一次轮询,然后让这个线程休眠。我想知道的是,这是在 swift 3 中执行此操作的正确方法吗?
您有 2 个选择:
- 使用
NSTimer
- 使用
DispatchSourceTimer
使用 NSTimer
非常简单,但它需要一个活动的 运行 循环,所以如果你需要在后台线程上进行轮询,事情可能会有点棘手,因为你需要创建一个线程并在其上保持 运行 循环(可能计时器本身将使 运行 循环保持活动状态)。
另一方面,DispatchSourceTimer
使用 queues
工作。您可以从系统提供的队列之一轻松创建调度源计时器或创建一个。
var timer: DispatchSourceTimer?
let queue = DispatchQueue.global(qos: .background)
guard let timer = DispatchSource.makeTimerSource(queue: queue) else { return }
timer.scheduleRepeating(deadline: .now(), interval: .seconds(100), leeway: .seconds(1))
timer.setEventHandler(handler: {
// Your code
})
timer.resume()
leeway
参数是系统可以延迟计时器的时间量。
Swift5,iOS10.0+
已接受答案中的代码不再编译,可以将其修改(并简化!)为:
DispatchQueue.global(qos: .userInitiated).async {
let timer = Timer.scheduledTimer(withTimeInterval: 100, repeats: true) { timer in
// Your action
}
timer.fire()
}
Swift 4 & Swift 5
var timer: Timer? //declare outside function scope
var runCount = 0
self.timer = Timer(timeInterval: 2.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: true)
guard let timer = self.timer else {return}
RunLoop.main.add(self.timer, forMode: RunLoop.Mode.default)
@objc func fireTimer() {
print("Timer fired! \(runCount)")
runCount += 1
if runCount == 5 {
timer?.invalidate() //stop the timer
}
}
或
self.timer = Timer.init(timeInterval: 1.0, repeats: true, block: { (timer) in
print("\n--------------------TIMER FIRED--------------\n")
runCount += 1
if runCount == 5{
timer.invalidate()
}
})
guard let timer = self.timer else {return}
RunLoop.main.add(self.timer!, forMode: RunLoopMode.defaultRunLoopMode)
我对其他编程语言有很多经验,但在swift 方面没有那么多 3. 我想做轮询循环。这是我写的:
DispatchQueue.global(qos: .userInitiated).async {
[unowned self] in
while self.isRunning {
WebService.getPeople(completion: nil)
sleep(100)
}
}
这对我来说很好,每 100 秒,我进行一次轮询,然后让这个线程休眠。我想知道的是,这是在 swift 3 中执行此操作的正确方法吗?
您有 2 个选择:
- 使用
NSTimer
- 使用
DispatchSourceTimer
使用 NSTimer
非常简单,但它需要一个活动的 运行 循环,所以如果你需要在后台线程上进行轮询,事情可能会有点棘手,因为你需要创建一个线程并在其上保持 运行 循环(可能计时器本身将使 运行 循环保持活动状态)。
另一方面,DispatchSourceTimer
使用 queues
工作。您可以从系统提供的队列之一轻松创建调度源计时器或创建一个。
var timer: DispatchSourceTimer?
let queue = DispatchQueue.global(qos: .background)
guard let timer = DispatchSource.makeTimerSource(queue: queue) else { return }
timer.scheduleRepeating(deadline: .now(), interval: .seconds(100), leeway: .seconds(1))
timer.setEventHandler(handler: {
// Your code
})
timer.resume()
leeway
参数是系统可以延迟计时器的时间量。
Swift5,iOS10.0+
已接受答案中的代码不再编译,可以将其修改(并简化!)为:
DispatchQueue.global(qos: .userInitiated).async {
let timer = Timer.scheduledTimer(withTimeInterval: 100, repeats: true) { timer in
// Your action
}
timer.fire()
}
Swift 4 & Swift 5
var timer: Timer? //declare outside function scope
var runCount = 0
self.timer = Timer(timeInterval: 2.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: true)
guard let timer = self.timer else {return}
RunLoop.main.add(self.timer, forMode: RunLoop.Mode.default)
@objc func fireTimer() {
print("Timer fired! \(runCount)")
runCount += 1
if runCount == 5 {
timer?.invalidate() //stop the timer
}
}
或
self.timer = Timer.init(timeInterval: 1.0, repeats: true, block: { (timer) in
print("\n--------------------TIMER FIRED--------------\n")
runCount += 1
if runCount == 5{
timer.invalidate()
}
})
guard let timer = self.timer else {return}
RunLoop.main.add(self.timer!, forMode: RunLoopMode.defaultRunLoopMode)