以下代码片段在完成块外部调用时效果很好,但是当我在块内部设置它时,定时器永远不会被触发。我不明白为什么会有区别:
$scope.playPage = function(data){
console.log(data);
//$http.post(url, data, config);
};
$scope.gameBoardDto = {
player1:"0",
player2:"0",
topleft:".",
...
...
};
$http({
method: 'POST',
url: 'http://localhost:8080/play',
data: $scope.gameBoardDto,
headers: {'Content-Type': 'application/json;charset=UTF-8'}
...
我最初在块外调用它时没有使用自引用,但是一旦进入内部,就需要它。然而,我再次在块外测试完全相同的代码,它仍然可以工作。
该块是在获得self.timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(self.foo),
userInfo: nil,
repeats: true)
相关信息的许可后调用的完成处理程序。
答案 0 :(得分:45)
问题是有问题的完成块可能没有在主线程上运行,因此没有运行循环。但是定时器需要在运行循环上进行调度,而主线程有一个,大多数后台线程都没有(除非你自己添加一个)。
要解决这个问题,在该完成处理程序中,将计时器的创建发送回主线程,它应该可以正常工作:
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true)
}
或者使用调度源计时器(可以为后台队列安排的计时器,并且不需要运行循环)。
var timer: DispatchSourceTimer!
private func startTimer() {
let queue = DispatchQueue(label: "com.domain.app.timer")
timer = DispatchSource.makeTimerSource(queue: queue)
timer.setEventHandler { [weak self] in
// do something
}
timer.schedule(deadline: .now(), repeating: 1.0)
timer.resume()
}
有关早期版本Swift的语法,请参阅previous revision of this answer。
答案 1 :(得分:1)
Timer()可能无法正常工作的另一个原因是它的创建方式。我有同样的问题,我尝试过的所有方法都没有解决,包括在主线程上实例化。我凝视了好一阵子,直到我(愚蠢地)意识到我正在以不同的方式创建它。代替Timer.scheduledTimer
我使用
实例化了它 let timer = Timer(timeInterval: 4.0, target: self, selector: #selector(self.timerCompletion), userInfo: nil, repeats: true)
就我而言,我必须将其实际添加到运行循环中才能使其运行。像这样
RunLoop.main.add(timer, forMode: RunLoop.Mode.default)
答案 2 :(得分:0)
这听起来似乎很明显,但是我有一个类似的问题,计时器不会触发,原因是它不在主线程中……没有错误,只是从未触发过。
放入主线程,至少您可以尝试一下!
DispatchQueue.main.async {
//insert your timer here
}