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

使用guard let实例化视图控制器时按钮失效,用let正常的原因咨询

无Storyboard开发下按钮失效的原因与解决办法

问题背景

我正在开发一个简易注册页面,希望通过按钮以模态方式展示下一个视图。但当我使用guard let从storyboard实例化SecondViewController时,按钮完全无法工作;而直接用let初始化SecondViewController时,功能正常。我已删除main.storyboard,练习无Storyboard开发,想了解出现该差异的原因。

相关代码

第一视图控制器代码

let signUpButton : UIButton = {
    let lButtonSettings = UIButton()
    lButtonSettings.translatesAutoresizingMaskIntoConstraints = false
    lButtonSettings.setTitle("Sign Up", for: .normal)
    lButtonSettings.setTitleColor(.systemRed, for: .normal)
    lButtonSettings.setTitleColor(.systemIndigo, for: .selected)
    lButtonSettings.addTarget(self, action: #selector(pressButton), for: .touchUpInside)
    
    return lButtonSettings
}()


@IBAction func pressButton(_ sender : UIButton) {
    guard let viewController = storyboard?.instantiateViewController(identifier: "SecondViewController") else {return}
    //let viewController = SecondViewController() -> worked code
    viewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen
    present(viewController, animated: true, completion: nil)
}

SceneDelegate代码

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
    guard let scene = (scene as? UIWindowScene) else { return }
    window = UIWindow(windowScene: scene)
    let mainViewController = UINavigationController(rootViewController: viewController())
    window?.rootViewController = mainViewController
    window?.makeKeyAndVisible()
}

原因分析

  • storyboard属性为空:你已经删除了main.storyboard,且当前视图控制器是通过纯代码方式初始化的,它的storyboard属性值为nil。执行guard let viewController = storyboard?.instantiateViewController(...)时,会直接触发else分支返回,根本不会执行后续的present操作,所以按钮看起来没有反应。
  • 直接初始化的有效性:let viewController = SecondViewController()是纯代码实例化视图控制器的方式,完全不依赖storyboard资源,因此能正常创建控制器实例并完成模态跳转,功能自然正常。

解决方案

  1. 保持纯代码初始化方式:既然是无Storyboard开发,就彻底放弃storyboard?.instantiateViewController()这类依赖storyboard的方法,继续使用SecondViewController()直接初始化。
  2. 修复按钮的潜在引用问题:你在闭包中初始化按钮时直接使用self添加target,可能会引发循环引用。建议将添加target的逻辑移到viewDidLoad中:
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(signUpButton)
    // 在这里添加target
    signUpButton.addTarget(self, action: #selector(pressButton), for: .touchUpInside)
    // 补充布局约束代码...
}

// 按钮初始化时移除addTarget代码
let signUpButton : UIButton = {
    let lButtonSettings = UIButton()
    lButtonSettings.translatesAutoresizingMaskIntoConstraints = false
    lButtonSettings.setTitle("Sign Up", for: .normal)
    lButtonSettings.setTitleColor(.systemRed, for: .normal)
    lButtonSettings.setTitleColor(.systemIndigo, for: .selected)
    return lButtonSettings
}()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:40:18