gpt4 book ai didi

ios - Swift Timer.scheduledTimer() 不起作用

转载 作者:搜寻专家 更新时间:2023-10-30 21:49:51 25 4
gpt4 key购买 nike

我的 swift 应用程序中有两个 View 。我正在执行如下的 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 更新。

因此,由于您从 URLSession 完成闭包(在后台队列上运行)调用 performSegue,它实际上正在运行 viewDidLoad也来自后台队列。因此,安排计时器的尝试失败了。要解决这个问题,您必须手动将 performSegue 代码分派(dispatch)到主队列:

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

if isPassed != "null" {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "gotoGame", sender: ...)
}
}
}

如果您不确定某些代码是否正在主队列上运行,请参阅 the documentation .或者您可以使用调度前提条件:

dispatchPrecondition(condition: .onQueue(.main))

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


与您当前的问题无关,但顺便说一句,为了避免计时器和 View Controller 之间的强引用循环,您通常希望保留对计时器的引用,以便您可以 invalidate当 View 消失时(例如,在 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 或更高版本中,您可以使用基于 block 的变体,将 weak 引用到 self,并在 中使用 invalidate >取消初始化:

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")
}

}

关于ios - Swift Timer.scheduledTimer() 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43755587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com