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

为何需两次调用协议函数才能生效?iOS代理模式问题求助

iOS 协议-代理功能问题修复方案

核心问题分析

你的代码存在几个关键错误,导致必须两次调用协议方法才能生效:

  • SecondViewController错误遵守了自身定义的协议,还在返回按钮点击时自行调用协议方法,完全没必要
  • FirstViewController中额外实例化了SecondViewController对象,这个实例和segue跳转创建的VC不是同一个,导致数据无法正确传递
  • FirstViewController的协议方法实现逻辑错误,没有直接更新UI,反而去读取错误实例的属性

分步修正

1. 修正SecondViewController

移除VC对自身协议的遵守,删除多余的协议方法实现,只保留代理调用逻辑:

import UIKit

protocol SecondViewControllerDelegate {
    func changeLabelText(name: String)
}

class SecondViewController: UIViewController {
    
    var delegate: SecondViewControllerDelegate?
    
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var backButton: UIButton!

    @IBAction func backButtonPressed(_ sender: UIButton) {
        let inputName = nameTextField.text ?? ""
        // 只需要调用代理的方法传递数据
        delegate?.changeLabelText(name: inputName)
        dismiss(animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

2. 修正FirstViewController

删除无用的SecondViewController实例,正确实现协议方法并直接更新Label:

import UIKit

class FirstViewController: UIViewController, SecondViewControllerDelegate {
    
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var button: UIButton!
    
    // 移除多余的secondVC实例(和segue创建的不是同一个对象)
    // let secondVC = SecondViewController()
    
    // 协议方法直接用传递过来的参数更新Label
    func changeLabelText(name: String) {
        nameLabel.text = name
    }
    
    @IBAction func buttonPressed(_ sender: UIButton) {
        performSegue(withIdentifier: "goToSecondVC", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destinationVC = segue.destination as? SecondViewController
        destinationVC?.delegate = self
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 移除错误的初始化赋值(secondVC是无效实例)
        // nameLabel.text = secondVC.enteredName
    }
}

关键修改说明

  • SecondViewController无需遵守自身协议:协议是用来定义外部对象需要实现的方法,VC本身只需要持有代理对象并触发方法即可
  • 删除多余的VC实例:segue跳转时系统会自动创建SecondViewController实例,你自行实例化的对象和界面上的VC完全无关,会导致数据不互通
  • 协议方法直接更新UI:代理方法的核心作用就是把SecondVC的数据传递给FirstVC,直接在方法里用参数更新Label即可,无需额外中转

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:05:13