我的swift应用程序中有两个视图.我正在执行如下的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()
}
Run Code Online (Sandbox Code Playgroud)
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")
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 17
定时器不适用于后台队列(没有一些涉及创建运行循环或在现有运行循环上手动调度它的手段).但是你绝不应该从主队列以外的任何东西发起任何UI更新.
因此,由于您是performSegue从URLSession完成闭包调用(在后台队列上运行),它实际上也是viewDidLoad从后台队列运行的.因此,计划定时器的尝试失败.要解决这个问题,您必须手动将performSegue代码分派到主队列:
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
...
if isPassed != "null" {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "gotoGame", sender: ...)
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不确定某些代码是否在主队列上运行,请参阅文档.或者您可以使用调度前提条件:
dispatchPrecondition(condition: .onQueue(.main))
Run Code Online (Sandbox Code Playgroud)
这样,如果您不小心从后台队列中调用了代码,它将(在调试版本中)停止应用程序.
与您当前的问题无关,但另外,为了避免计时器和视图控制器之间的强引用周期,您通常希望保留对计时器的引用,以便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")
}
}
Run Code Online (Sandbox Code Playgroud)
或在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")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6902 次 |
| 最近记录: |