You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:35:03