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

从Xib弹窗UIView的TextField传数据到ViewController遇阻求助

弹窗UIView数据回传问题:TextField代理中delegate为nil,保存按钮点击时name为空

在获取弹窗UIView的用户输入数据时遇到两个异常:

  • TextFieldDelegate的textFieldDidEndEditing方法中,能正确获取并打印输入的name值,但打印delegate为nil,导致无法调用saveName回传数据;
  • 点击保存按钮时,能正常打印delegate(指向ViewController),但打印name为空,回传的也是空值。

需求是将用户输入的name变量正确传回ViewController。


ViewController 代码

class ViewController: UIViewController {

     var popUp: PopUp?

     override func viewDidLoad() {
          super.viewDidLoad()
     }
}

extension ViewController: PopUpDelegate {

     func saveName(_ name: String) {
          print(name) // 测试打印
     }

     @IBAction func popUpButton(_ sender: UIButton) {
          self.popUp = PopUp(frame: self.view.frame, sender: self)
          self.view.addSubview(popUp!)
     }
}
class PopUp: UIView {

     @IBOutlet weak var textOutlet: UITextField!
     var delegate: PopUpDelegate?
     var name = ""
     
     override func awakeFromNib() {
          super.awakeFromNib()
          textOutlet.delegate = self
     }

     required init?(coder: NSCoder) {
          super.init(coder: coder)
     }

     init(frame: CGRect, sender: PopUpDelegate) {
          super.init(frame: frame)
          xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
          self.delegate = sender
     }

     func xibSetup(frame: CGRect) {
          let view = loadXib()
          view.frame = frame
          addSubview(view)
     } 
    
     func loadXib() -> UIView {
          let bundle = Bundle(for: type(of: self))
          let nib = UINib(nibName: "PopUp", bundle: bundle)
          let view = nib.instantiate(withOwner: self, options: nil).first as? UIView
          return view!
     }

     @IBAction func cancelButton(_ sender: UIButton) {
          self.removeFromSuperview()
     }

     @IBAction func saveButton(_ sender: UIButton) {
          print(delegate) // 打印ViewController
          print(name) // 打印空字符串
          delegate?.saveName(name) // 回传空值
          self.removeFromSuperview()
     }
}

extension PopUp: UITextFieldDelegate {

     func textFieldShouldReturn(_ textField: UITextField) -> Bool {
          if textField.text != "" {
               textField.endEditing(true)
               return true
          } else {
               textField.placeholder = "name required*"
          }
          return true
     }
    
     func textFieldDidEndEditing(_ textField: UITextField) {
          if textField.text != "" {
               name = textField.text! 
               print(delegate) // 打印nil
               print(name) // 打印输入的文本
               delegate?.saveName(name) // 无响应
          } else {
               textField.placeholder = "name required*"
          }
     }
}

protocol PopUpDelegate {
    func saveName(_ name: String)
}

问题根源与修复方案

问题1:textFieldDidEndEditing中delegate为nil

原因:通过nib.instantiate(withOwner: self, options: nil)加载XIB时,系统会额外创建一个PopUp实例作为XIB的owner,你设置delegate的是外层的PopUp实例,但XIB内部的TextField实际关联的是这个新创建的owner实例,它的delegate未被赋值,所以打印nil。

修复步骤:

  1. 在XIB中给根视图添加IBOutlet,命名为contentView(确保根视图的class设置为PopUp);
  2. 修改loadXib方法,让XIB控件直接关联当前PopUp实例:
func loadXib() -> UIView {
    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: "PopUp", bundle: bundle)
    nib.instantiate(withOwner: self, options: nil)
    return contentView
}
  1. 调整init(frame:sender:)的时序,先赋值delegate再加载XIB:
init(frame: CGRect, sender: PopUpDelegate) {
    super.init(frame: frame)
    self.delegate = sender
    xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}

问题2:保存按钮点击时name为空

原因:当前代码中name变量只有在textFieldDidEndEditing触发时才会被赋值,但用户可能直接点击保存按钮而不触发结束编辑,此时name还是初始空字符串。

修复步骤:
点击保存按钮时,直接从textOutlet获取最新文本,移除冗余的name变量:

@IBAction func saveButton(_ sender: UIButton) {
    guard let inputName = textOutlet.text, !inputName.isEmpty else {
        textOutlet.placeholder = "name required*"
        return
    }
    delegate?.saveName(inputName)
    self.removeFromSuperview()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:52:47