Swift-Xcode中unwindSegue无法传递UserDefaults数据问题
问题分析与解决方案
我来帮你解决这个unwind segue时UserDefaults数据不更新的问题,核心原因和修复方法如下:
为什么unwind segue时数据不更新?
你的TokenController中,returnValue是在控制器初始化阶段直接读取UserDefaults的:
var returnValue: Int = UserDefaults.standard.integer(forKey: "tokens")
而viewDidLoad只会在控制器第一次加载视图时执行一次。当你用unwind segue回到TokenController时,这个控制器实例早就已经存在了——它不是像push segue那样新建的实例,所以不会重新初始化returnValue,也不会再次执行viewDidLoad。这就导致标签显示的还是旧数据,而不是你刚存在UserDefaults里的新值。
修复步骤
1. 重构TokenController,添加手动刷新方法
把读取UserDefaults和更新UI的逻辑抽成单独的方法,这样可以在需要的时候(比如unwind回来时)手动调用:
import UIKit class TokenController: UIViewController { @IBOutlet var tokens: UILabel! @IBOutlet var minus1: UIButton! @IBOutlet var minus2: UIButton! var returnValue: Int = 0 // 先初始化为默认值 override func viewDidLoad() { super.viewDidLoad() updateTokenUI() // 首次加载时刷新UI } // 专门用来刷新token数据和UI的方法 private func updateTokenUI() { returnValue = UserDefaults.standard.integer(forKey: "tokens") tokens.text = "x\(returnValue)" } @IBAction func unwindSegue(_ sender: UIStoryboardSegue) { // 当unwind回到这个控制器时,手动刷新UI updateTokenUI() } }
2. 修复FirstViewController中的变量错误
你的FirstViewController代码里有一个隐藏bug:if (returnValue != 30)中的returnValue是未定义的(它只在alert的handler闭包里存在),这会导致编译错误。我们需要提前获取当前的token值来判断是否显示"Continue Playing"按钮:
@IBAction func Button1(_ sender: Any) { let randomNumber = arc4random_uniform(3) + 1 let i = Int(randomNumber) // 提前获取当前的token值,用于后续判断 let currentTokens = UserDefaults.standard.integer(forKey: "tokens") let alert = UIAlertController(title: "Congratulations", message: "You earned \(i) tokens!", preferredStyle: .alert) alert.setTitleImage(UIImage(named: "token")) // "Let's See!"按钮逻辑 alert.addAction(UIAlertAction(title: "Let's See!", style: .default, handler: { (action) in var updatedTokens = UserDefaults.standard.integer(forKey: "tokens") updatedTokens += i UserDefaults.standard.set(updatedTokens, forKey:"tokens") self.performSegue(withIdentifier: "unwindSegue", sender: nil) })) // 用提前获取的currentTokens判断,避免未定义变量错误 if currentTokens != 30 { alert.addAction(UIAlertAction(title: "Continue Playing", style: .default, handler: { (action) in var updatedTokens = UserDefaults.standard.integer(forKey: "tokens") updatedTokens += i UserDefaults.standard.set(updatedTokens, forKey:"tokens") self.performSegue(withIdentifier: "continue", sender: self) })) } self.present(alert, animated: true, completion: nil) }
为什么这样修改有效?
- 把读取UserDefaults的逻辑从属性初始化移到了
updateTokenUI方法,每次调用这个方法都会重新读取最新的值,确保数据是最新的。 - 在unwind segue的回调方法里手动调用刷新逻辑,因为unwind回到已存在的控制器时,不会自动触发
viewDidLoad,必须手动刷新UI。 - 修复了FirstViewController中的变量未定义问题,避免编译错误。
内容的提问来源于stack exchange,提问作者Kinja
相关产品推荐
相关产品推荐

