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

如何在TabBarController管理的两个ViewController间传递布尔值

披萨点击游戏的升级传值问题

我正在开发一款点击披萨赚钱的游戏,初始点击仅能获得1美元,购买升级后收益会提升。理论上点击1级升级按钮后,应让主游戏视图的单次点击收益变为5美元,但尝试了各种解决方案都无效。

我的GameViewController代码如下:

import UIKit

class GameViewController: UIViewController {
    var wallet: Int = 0
    var totalIncome: Int = 0
    var level1UpgradeUsed: Bool = false
    @IBOutlet weak var pizzaButton: UIButton!
    @IBOutlet weak var labelWallet: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        print(level1UpgradeUsed)
        // Do any additional setup after loading the view.
    }
    
    
    @IBAction func pizzaClick(_ sender: Any) {
        let upgrades = UpgradesViewController()
        
        let level1UpgradeUsed = upgrades.level1used
        if level1UpgradeUsed == true {
            wallet = wallet + 4
        }
        
        wallet = wallet + 1
        labelWallet.text = ("$" + String(wallet))
    }
}

UpgradesViewController代码:

import UIKit

class UpgradesViewController: UIViewController {

    public var level1used: Bool = false
    public var level2used: Bool = false
    public var level3used: Bool = false
    public var level4used: Bool = false
    var level5used: Bool = false
    @IBOutlet weak var buttonLevel1: UIButton!
    @IBOutlet weak var buttonLevel2: UIButton!
    @IBOutlet weak var buttonLevel3: UIButton!
    @IBOutlet weak var buttonLevel4: UIButton!
    @IBOutlet weak var buttonLevel5: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let gameViewController = segue.destination as? GameViewController {
            gameViewController.level1UpgradeUsed = self.level1used
        }
    }
    
    @IBAction func Level1Click(_ sender: Any) {
        if level1used == false{
            buttonLevel1.backgroundColor = UIColor.gray
            level1used = true
        }
        else {
            
        }
    }
}

我猜测自己未正确利用TabBarController进行传值,但完全不知该如何操作。我是Swift新手,正在自学相关内容,麻烦帮忙解决。


问题原因

  1. 实例不共享:在pizzaClick方法里你新建了UpgradesViewController实例,这是一个全新的对象,和TabBar里实际显示的升级页面不是同一个,所以永远拿不到用户点击升级后的true值。
  2. Segue传值无效:prepare(for segue:)仅在通过Storyboard的segue跳转时生效,而TabBarController的页面切换不会触发这个方法,所以你的传值逻辑根本没起作用。

解决方案

方案1:通过TabBarController获取已存在的升级页面实例

直接从当前的TabBarController中找到已经加载的UpgradesViewController实例,而不是新建:

修改GameViewController的pizzaClick方法:

@IBAction func pizzaClick(_ sender: Any) {
    // 从TabBarController中获取UpgradesViewController实例
    guard let tabBar = self.tabBarController,
          let upgradesVC = tabBar.viewControllers?.first(where: { $0 is UpgradesViewController }) as? UpgradesViewController else {
        return
    }
    
    // 根据升级状态增加收益
    if upgradesVC.level1used {
        wallet += 4
    }
    wallet += 1
    labelWallet.text = "$\(wallet)"
}

方案2:用单例统一管理游戏数据(推荐)

创建一个全局的游戏数据管理单例,所有页面都共享同一个数据源,避免页面间传值的麻烦,后续扩展功能也更方便:

  1. 创建GameDataManager.swift文件:
import UIKit

class GameDataManager {
    // 单例实例,全局唯一
    static let shared = GameDataManager()
    
    // 私有初始化,禁止创建多个实例
    private init() {}
    
    // 存储游戏数据
    var wallet: Int = 0
    var totalIncome: Int = 0
    var level1used: Bool = false
    var level2used: Bool = false
    var level3used: Bool = false
    var level4used: Bool = false
    var level5used: Bool = false
}
  1. 修改GameViewController:
import UIKit

class GameViewController: UIViewController {
    @IBOutlet weak var pizzaButton: UIButton!
    @IBOutlet weak var labelWallet: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始化显示当前钱包金额
        labelWallet.text = "$\(GameDataManager.shared.wallet)"
    }
    
    @IBAction func pizzaClick(_ sender: Any) {
        let gameData = GameDataManager.shared
        
        // 应用升级收益
        if gameData.level1used {
            gameData.wallet += 4
        }
        gameData.wallet += 1
        // 更新显示
        labelWallet.text = "$\(gameData.wallet)"
    }
}
  1. 修改UpgradesViewController:
import UIKit

class UpgradesViewController: UIViewController {
    @IBOutlet weak var buttonLevel1: UIButton!
    @IBOutlet weak var buttonLevel2: UIButton!
    @IBOutlet weak var buttonLevel3: UIButton!
    @IBOutlet weak var buttonLevel4: UIButton!
    @IBOutlet weak var buttonLevel5: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 页面加载时恢复按钮状态
        let gameData = GameDataManager.shared
        buttonLevel1.backgroundColor = gameData.level1used ? .gray : .systemBlue
        // 其他升级按钮同理处理状态
    }
    
    @IBAction func Level1Click(_ sender: Any) {
        let gameData = GameDataManager.shared
        if !gameData.level1used {
            buttonLevel1.backgroundColor = .gray
            gameData.level1used = true
        }
    }
}

方案优势对比

  • 方案1适合简单场景,快速解决当前传值问题,但后续如果添加更多升级或数据,会越来越繁琐。
  • 方案2用单例统一管理数据,所有页面共享同一状态,后续添加进度保存(比如用UserDefaults)、更多升级类型都会更轻松,是游戏开发中常用的模式。

内容的提问来源于stack exchange,提问作者Mason Ferrie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 11:45:28