Swift中如何从Timer触发的函数返回值并跨文件获取howHungry更新值?
Timer更新值无法回传的问题解决
问题描述
创建了一个每5秒触发的Timer,timerFire函数接收来自file1.swift的Double类型值howHungry,每次触发将其减1,但更新后的值无法传回file1,导致控制台重复输出初始值(例如"Hunger value is 14.0")。
原代码
file1.swift
let hungerTimer = myTimer() hungerTimer.startTimer(timerInitialValue: howHungry)
file2.swift
func startTimer(timerInitialValue:Double){ if timer == nil{ //如果不存在饥饿计时器则创建新的 timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(timerFire(sender:)), userInfo: timerInitialValue/*饥饿值*/, repeats: true) print("New Timer Started") }else{ //如果计时器已存在,先停止再启动新的 timer!.invalidate() timer = nil print("Old Timer Stopped") timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(timerFire(sender:)), userInfo: timerInitialValue, repeats: true) print ("Now New Timer Started") print(timer) } } @objc func timerFire(sender: Timer) -> Double{ //从Timer获取饥饿值 var hungryDouble = sender.userInfo as! Double //减1 hungryDouble -= 1.0 print("Hunger value is \(hungryDouble)") return(hungryDouble) }
问题原因
- 值类型传递特性:Double是值类型,传给Timer的
userInfo是初始值的副本,timerFire里修改的只是这个副本,不会影响file1中的原变量。 - Timer selector无法接收返回值:
timerFire的返回值完全没用,因为Timer通过selector调用方法时,不会处理返回值,所以更新后的值根本传不回file1。
解决方案
方案一:闭包回调(推荐)
通过闭包将更新后的值回调给file1,这是Swift中跨文件传递更新值的常用方式。
修改后的file2.swift
class myTimer { var timer: Timer? // 定义回调闭包,用于传递更新后的饥饿值 var onHungerUpdated: ((Double) -> Void)? func startTimer(timerInitialValue: Double) { // 先停止已有计时器 timer?.invalidate() timer = nil var currentHunger = timerInitialValue // 使用block式Timer,避免selector的局限 timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { [weak self] _ in currentHunger -= 1.0 print("饥饿值为 \(currentHunger)") // 调用闭包传递更新后的值 self?.onHungerUpdated?(currentHunger) } print("新计时器已启动") } }
修改后的file1.swift
// 假设howHungry是file1中的变量 var howHungry: Double = 14.0 let hungerTimer = myTimer() // 设置回调,接收更新后的饥饿值 hungerTimer.onHungerUpdated = { updatedValue in howHungry = updatedValue // 这里可以添加UI更新等逻辑 } hungerTimer.startTimer(timerInitialValue: howHungry)
方案二:使用引用类型包装值
把Double包装成类(引用类型),这样传递的是实例引用,修改时会直接改变原对象的值。
定义包装类
class HungerWrapper { var value: Double init(value: Double) { self.value = value } }
修改后的file2.swift
class myTimer { var timer: Timer? func startTimer(hungerWrapper: HungerWrapper){ timer?.invalidate() timer = nil timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(timerFire(sender:)), userInfo: hungerWrapper, repeats: true) print("新计时器已启动") } @objc func timerFire(sender: Timer){ guard let hungerWrapper = sender.userInfo as? HungerWrapper else { return } hungerWrapper.value -= 1.0 print("饥饿值为 \(hungerWrapper.value)") } }
修改后的file1.swift
let hungerWrapper = HungerWrapper(value: 14.0) let hungerTimer = myTimer() hungerTimer.startTimer(hungerWrapper: hungerWrapper) // 后续可以通过hungerWrapper.value获取更新后的值
内容的提问来源于stack exchange,提问作者Gaz
相关产品推荐
相关产品推荐

