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

Swift编程式呈现ViewController失败问题求助

问题分析与解决方案

先直接回应你的疑问:大小写拼写错误确实是你遇到问题的核心原因之一,同时还有属性初始化时机、视图控制器实例化逻辑的问题,我来一步步帮你解决:


一、先解决最基础的「未声明类型」错误(Use of undeclared type 'GameoverViewController')

Swift对大小写极其敏感,你需要确保:

  1. 你的GameoverViewController.swift文件中,类名必须是大写开头的GameoverViewController,和文件名完全一致:
import UIKit
// 注意G、V、C都是大写
class GameoverViewController: UIViewController {
    // 你的界面逻辑代码
}
  1. 确认这个文件已经添加到项目的Target中:在Xcode里选中该文件,右侧「File Inspector」的「Target Membership」勾选你的App target,避免文件被排除在编译外。
  2. 在Storyboard中绑定类:打开Gameover.storyboard,选中对应的ViewController,右侧「Identity Inspector」的「Class」下拉选择GameoverViewController,确保没有选错或拼写错误。

二、修复「属性初始化器中无法使用实例成员」错误

你最初的代码在类的属性初始化阶段就尝试用storyBoard实例化gameoverViewController,但此时self还未完全初始化,不能访问其他实例属性。更合理的做法是在需要跳转的时候再实例化视图控制器,避免提前占用内存:


三、修复视图控制器跳转的类型错误

不需要强制把GameoverViewController转成UIViewController,因为它本身就是UIViewController的子类,直接present即可。另外要注意:触发跳转时必须先停止timer,否则timer会持续运行,不断尝试弹出新界面导致崩溃。


最终修复后的完整代码

import UIKit
class ViewController: UIViewController {
    var wantedLiter = 10.00
    var timer: Timer?
    var actualLiter = 0.00
    var timerReset = true
    let preisProLiter = 1.26 // 用let更合适,因为值不会改变

    @IBOutlet weak var preisliterLabel: UILabel!
    @IBOutlet weak var euroLabel: UILabel!
    @IBOutlet weak var numberLabel: UILabel!
    @IBOutlet weak var numberButton: UIButton!
    @IBOutlet weak var confirmButton: UIButton!

    @IBAction func confirm(_ sender: Any) {
        // 这里可以添加确认按钮的逻辑
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        numberLabel.text = String(round(1000*actualLiter)/1000)
        preisliterLabel.text = String(preisProLiter)
    }

    @IBAction func holdingTheButton(_ sender: Any) {
        print("I am holding")
        timerReset = false
        guard timer == nil else { return }
        timer = Timer.scheduledTimer(timeInterval: 0.005, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
    }

    @IBAction func buttonReleased(_ sender: Any) {
        print("button released")
        if wantedLiter == actualLiter {
            print("WIN!")
            actualLiter = 0
            // 重置显示内容
            numberLabel.text = String(round(1000*actualLiter)/1000)
            euroLabel.text = String((round(100*actualLiter*preisProLiter)/100))
        }
        timer?.invalidate()
        timer = nil
    }

    @objc func updateTime(){
        print("updating label ")
        guard wantedLiter > actualLiter else {
            // 触发Gameover条件
            print("Ooops")
            // 先停止timer,避免重复触发跳转
            timer?.invalidate()
            timer = nil
            actualLiter = 0
            // 重置显示内容
            numberLabel.text = String(round(1000*actualLiter)/1000)
            euroLabel.text = String((round(100*actualLiter*preisProLiter)/100))
            
            // 实例化并跳转Gameover界面
            let storyBoard = UIStoryboard(name: "Gameover", bundle: nil)
            guard let gameoverVC = storyBoard.instantiateViewController(withIdentifier: "overID") as? GameoverViewController else {
                print("Failed to load GameoverViewController, check Storyboard ID!")
                return
            }
            self.present(gameoverVC, animated: true, completion: nil)
            return
        }
        
        actualLiter += 0.01
        numberLabel.text = String(round(1000*actualLiter)/1000)
        euroLabel.text = String((round(100*actualLiter*preisProLiter)/100))
    }
}

最后再检查一个关键细节

确认Gameover.storyboard中对应的ViewController的Storyboard ID是overID,和代码里的字符串完全一致(大小写也要匹配),否则会出现实例化失败的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:12:39