UICollectionView不保留UITextField输入内容问题求助
这个问题其实是UICollectionView单元格复用机制导致的——当你滚动MainCollectionView时,离开屏幕的MainCell会被回收复用,它内部的NestedCollectionView也会跟着被重置,而你之前输入的文本只存在于被回收的NestedCell的TextField里,自然就丢失了。核心解法是用数据模型保存输入状态,让UI始终从数据源读取内容,具体步骤如下:
第一步:为嵌套条目创建独立的数据模型
不要再依赖控件保存输入内容,给每个NestedCell创建一个数据模型,用来记录它的类型(Label/TextField)和当前文本:enum NestedItemType { case label case textField } struct NestedItem { var type: NestedItemType var content: String // 这里存默认值或用户输入的文本 }同时,MainCollectionView的数据源要改成保存每个MainCell对应的嵌套数据数组,比如:
var mainDataSource: [[NestedItem]] = [],每个元素对应一个MainCell的NestedCollectionView数据。第二步:让NestedCell支持数据绑定与回调
在NestedCell里添加配置方法,从数据模型读取内容显示;同时添加回调,在文本变化时同步更新数据模型:class NestedCollectionViewCell: UICollectionViewCell { @IBOutlet weak var displayLabel: UILabel! @IBOutlet weak var inputTextField: UITextField! // 文本变化时的回调,用来更新数据模型 var onTextChanged: ((String) -> Void)? override func awakeFromNib() { super.awakeFromNib() // 监听文本输入变化 inputTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) // 监听编辑结束,确保最后一次输入被同步 inputTextField.addTarget(self, action: #selector(textFieldDidEndEdit(_:)), for: .editingDidEnd) } // 用数据模型配置cell func configure(with item: NestedItem) { displayLabel.isHidden = item.type != .label inputTextField.isHidden = item.type != .textField inputTextField.text = item.content displayLabel.text = item.content } @objc private func textFieldDidChange(_ textField: UITextField) { onTextChanged?(textField.text ?? "") } @objc private func textFieldDidEndEdit(_ textField: UITextField) { onTextChanged?(textField.text ?? "") } }第三步:在MainCell中绑定数据与回调
MainCell持有自己对应的嵌套数据数组,配置NestedCollectionView时,把数据传给NestedCell,并设置回调更新数据源:class MainCollectionViewCell: UICollectionViewCell { @IBOutlet weak var nestedCollectionView: UICollectionView! var nestedItems: [NestedItem] = [] { didSet { nestedCollectionView.reloadData() } } override func awakeFromNib() { super.awakeFromNib() nestedCollectionView.dataSource = self nestedCollectionView.delegate = self } } extension MainCollectionViewCell: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return nestedItems.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "NestedCell", for: indexPath) as! NestedCollectionViewCell let item = nestedItems[indexPath.item] cell.configure(with: item) // 设置回调,实时更新数据模型 cell.onTextChanged = { [weak self] newText in guard let self = self else { return } self.nestedItems[indexPath.item].content = newText } return cell } }第四步:配置MainCollectionView的数据源
在MainCollectionView的cellForItemAt方法中,把对应的嵌套数据传给MainCell:func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCell", for: indexPath) as! MainCollectionViewCell cell.nestedItems = mainDataSource[indexPath.item] return cell }
这样一来,不管MainCell怎么被复用,NestedCollectionView都会从数据源中读取最新的文本内容,用户输入的内容也会实时同步到数据模型里,滚动后自然不会丢失了。
内容的提问来源于stack exchange,提问作者marco

