Swift Timer.scheduledTimer()不起作用

我的快速应用程序中有两个视图。我正在执行以下segue。

ViewController.swift -----------------> GameViewController.swift

加载GameViewController时,还会将一个值数组从ViewController.swift传递给GameViewController.swift

计时器应在GameViewController.swift中初始化

我试图初始化一个计时器并通过它调用一个方法,但是它不起作用。

以下是我的代码段。

ViewController.swift

func signIn(difficultyLvl:String){

let username = usernameTxt.text

let password = passwordTxt.text

let url = URL(string: "http://192.168.1.106/speed/scoreBoardController.php?username="+username!+"&password="+password!+"&action=SIGNIN")

let task = URLSession.shared.dataTask(with: url!) {(data, response, error) in

let isPassed = String(data: data!, encoding:.utf8)?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

var gameViewControllerParams = [Int: [String: String]]()

gameViewControllerParams[0] = ["userId" : isPassed!]

gameViewControllerParams[1] = ["difficultyLvl" : difficultyLvl]

if(isPassed != "null"){

self.performSegue(withIdentifier: "gotoGame", sender: gameViewControllerParams)

}

}

task.resume()

}

GameViewController.swift

class GameViewController: UIViewController {

var gameViewControllerParams = [Int: [String: String]]()

override func viewDidLoad() {

super.viewDidLoad()

let _ = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(self.setCalculationLs), userInfo:nil,repeats: true)

}

func setCalculationLs(){

print("Timing")

}

}

回答:

计时器不适用于后台队列(不费吹灰之力就涉及创建运行循环或在现有运行循环上手动调度它)。但是无论如何,您绝不应该从主队列之外的任何其他位置启动任何UI更新。

因此,由于您是performSegueURLSession完成关闭(在后台队列中运行)调用的,因此它实际上也viewDidLoad从后台队列中运行。因此,计划计时器的尝试失败。要解决此问题,您必须手动将performSegue代码分发到主队列:

let task = URLSession.shared.dataTask(with: url!) { data, response, error in

...

if isPassed != "null" {

DispatchQueue.main.async {

self.performSegue(withIdentifier: "gotoGame", sender: ...)

}

}

}

如果您不确定主队列上是否正在运行某些代码,请参阅文档。或者,您可以使用调度先决条件:

dispatchPrecondition(condition: .onQueue(.main))

这样,如果您不小心从后台队列中调用了代码,它将(在调试版本中)停止应用程序。


与您当前的问题无关,但顺便说一句,为避免计时器和视图控制器之间的引用周期过长,通常需要保留对计时器的引用,以便invalidate在视图消失时可以使用它(例如,在viewDidAppear和中创建计时器)。将其删除viewDidDisappear)。否则,您可以GameViewController在将其关闭后保留它们,例如:

class GameViewController: UIViewController {

weak var timer: Timer?

override func viewDidAppear(_ animated: Bool) {

super.viewDidAppear(animated)

timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(setCalculationLs(_:)), userInfo: nil, repeats: true)

}

override func viewDidDisappear(_ animated: Bool) {

super.viewDidDisappear(animated)

timer?.invalidate()

}

@objc func setCalculationLs(_ timer: Timer) {

print("Tick")

}

}

或在iOS 10或更高版本中,您可以在和中使用基于块的变体,并weak参考:self``invalidate``deinit

class GameViewController: UIViewController {

weak var timer: Timer?

override func viewDidLoad() {

super.viewDidLoad()

timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in

self?.setCalculationLs()

}

}

deinit {

timer?.invalidate()

}

func setCalculationLs() {

print("Tick")

}

}

以上是 Swift Timer.scheduledTimer()不起作用 的全部内容, 来源链接: utcz.com/qa/430312.html

回到顶部