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

iOS MVC项目问题:无法通过Controller修改View内容

iOS MVC口令验证项目问题排查

我正在开发首个iOS MVC项目,功能为验证口令短语并开放用户权限,已创建以下3个文件:

1. Model:校验口令短语正确性

负责校验输入的口令是否正确,返回结果用于更新UILabel文本

import Foundation

class passwordCheck {
    public static let model = passwordCheck()
    
    func passwordChecking (_ word: String) -> String {
        if word == "leohl" {
            return "Hello"
        } else {
            return "Error"
        }
    }
}

2. View:展示UI元素

包含显示状态的UILabel和触发验证的UIButton

import UIKit

class View: UIView {
    
    public let helloLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .black
        label.text = "Password?"
        label.font = .systemFont(ofSize: 20, weight: .bold)
        label.frame = CGRect(x: UIScreen.main.bounds.width/2-75, y: UIScreen.main.bounds.height/2-300, width: 150, height: 30)
        return label
    }()
    
    public let startButton: UIButton = {
        let button = UIButton()
        button.setTitle("Start", for: .normal)
        button.backgroundColor = .red
        button.frame = CGRect(x: UIScreen.main.bounds.width/2-50, y: UIScreen.main.bounds.height/2-50, width: 100, height: 50)
        button.layer.cornerRadius = 5
        button.setTitleColor(.orange, for: .highlighted)
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        addSubview(helloLabel)
        addSubview(startButton)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
    }
}

3. ViewController:处理交互逻辑

点击按钮唤起输入弹窗,本应更新View的背景色和UILabel文本

import UIKit

class ViewController: UIViewController {
    let myView = View()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let safeArea = view.safeAreaLayoutGuide.layoutFrame
        let theView = View(frame: safeArea)
        theView.startButton.addTarget(self, action: #selector(alertCheck), for: .touchUpInside)
        view.addSubview(theView)
    }
    
    @objc func alertCheck() {
        callAlert(alertTitle: "Identify yourself", alertMessage: "Type the code phrase")
    }
    
    func callAlert(alertTitle: String, alertMessage: String) {
        let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { action in
            self.myView.helloLabel.text = passwordCheck.model.passwordChecking(alert.textFields?.first?.text ?? "")
        }))
        alert.addTextField()
        self.present(alert, animated: true)
        print("Button working")
    }
}

问题描述

所有功能看似正常,但在Alert中输入口令短语后,View中的UILabel内容无任何变化,终端报错信息如下:

-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] 执行输入操作需要有效的sessionID

问题原因及修复方案

核心问题

ViewController中创建了两个独立的View实例:

  • 全局声明的myView:仅初始化但从未添加到视图层级中
  • viewDidLayoutSubviews里创建的theView:被添加到界面上显示,但弹窗回调中修改的是myView的label,导致界面无更新

修改后的ViewController代码

import UIKit

class ViewController: UIViewController {
    let myView = View()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 在viewDidLoad中配置myView并添加到视图
        myView.startButton.addTarget(self, action: #selector(alertCheck), for: .touchUpInside)
        view.addSubview(myView)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        // 利用viewDidLayoutSubviews更新myView的frame以适配safeArea
        let safeArea = view.safeAreaLayoutGuide.layoutFrame
        myView.frame = safeArea
    }
    
    @objc func alertCheck() {
        callAlert(alertTitle: "Identify yourself", alertMessage: "Type the code phrase")
    }
    
    func callAlert(alertTitle: String, alertMessage: String) {
        let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { action in
            // 修改界面上实际显示的myView的label
            self.myView.helloLabel.text = passwordCheck.model.passwordChecking(alert.textFields?.first?.text ?? "")
            // 可选:添加背景色修改逻辑
            self.myView.backgroundColor = alert.textFields?.first?.text == "leohl" ? .green : .red
        }))
        alert.addTextField()
        self.present(alert, animated: true)
        print("Button working")
    }
}

关键修改点

  1. 移除viewDidLayoutSubviews中重复创建的theView实例,统一使用全局的myView
  2. 在viewDidLoad中为myView绑定按钮点击事件并添加到视图层级
  3. 在viewDidLayoutSubviews中更新myView的frame以适配安全区域
  4. 弹窗回调中修改的是界面上实际显示的myView的label,同时可添加背景色修改逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:27:05