Swift 4 UITableView设置单个可输入UITextView单元格并获取输入内容
嘿,我来帮你搞定这个需求!要在动态UITableView里加入可输入的UITextView单元格并监听输入,咱们可以按以下步骤来实现:
实现带可输入UITextView的UITableView方案
核心思路是区分普通内容单元格和输入单元格,通过自定义Cell来封装UI,再利用UITextView的代理/闭包回调获取用户输入内容。
1. 自定义两种UITableViewCell
先创建两个独立的Cell类,让代码结构更清晰:
普通内容单元格
用来展示数组里的静态内容:
class NormalContentCell: UITableViewCell { static let identifier = "NormalContentCell" // 展示内容的Label,可根据需求调整样式 private let contentLabel: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.numberOfLines = 0 label.font = .systemFont(ofSize: 16) return label }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { contentView.addSubview(contentLabel) NSLayoutConstraint.activate([ contentLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), contentLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16), contentLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12), contentLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12) ]) } // 配置单元格内容 func configure(with text: String) { contentLabel.text = text } }
带UITextView的输入单元格
封装输入框,并通过闭包回调实时传递输入内容:
class InputTextViewCell: UITableViewCell, UITextViewDelegate { static let identifier = "InputTextViewCell" let inputTextView: UITextView = { let textView = UITextView() textView.translatesAutoresizingMaskIntoConstraints = false textView.font = .systemFont(ofSize: 16) textView.backgroundColor = .systemGray6 textView.layer.cornerRadius = 8 textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) return textView }() // 文本变化回调闭包,用来传递输入内容给ViewController var textChangedHandler: ((String) -> Void)? override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() inputTextView.delegate = self } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { contentView.addSubview(inputTextView) NSLayoutConstraint.activate([ inputTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), inputTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16), inputTextView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), inputTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8), // 给输入框设置最小高度,避免过扁 inputTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 80) ]) } // UITextView代理方法,监听文本变化 func textViewDidChange(_ textView: UITextView) { textChangedHandler?(textView.text ?? "") } }
2. 在ViewController中完善数据源与Cell注册
首先在viewDidLoad里注册自定义Cell,同时开启TableView的自动高度适配:
override func viewDidLoad() { super.viewDidLoad() // 注册两种Cell tableView.register(NormalContentCell.self, forCellReuseIdentifier: NormalContentCell.identifier) tableView.register(InputTextViewCell.self, forCellReuseIdentifier: InputTextViewCell.identifier) // 开启自动高度,让输入框内容变多时Cell自动增高 tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 100 }
然后完善你已经写了一部分的数据源方法:
var array: [String] = ["内容1", "内容2", "内容3"] // 你的原始数据源数组 var userInputText: String = "" // 用来存储用户输入的文本 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return array.count + 1 // 多一行作为输入单元格 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 前array.count行是普通内容Cell if indexPath.row < array.count { let cell = tableView.dequeueReusableCell(withIdentifier: NormalContentCell.identifier, for: indexPath) as! NormalContentCell cell.configure(with: array[indexPath.row]) return cell } else { // 最后一行是输入Cell let cell = tableView.dequeueReusableCell(withIdentifier: InputTextViewCell.identifier, for: indexPath) as! InputTextViewCell // 恢复之前的输入内容(如果需要) cell.inputTextView.text = userInputText // 绑定回调,实时获取输入内容 cell.textChangedHandler = { [weak self] inputText in guard let self = self else { return } self.userInputText = inputText // 这里可以做实时处理,比如打印、更新数据等 print("当前输入:\(inputText)") } return cell } }
3. 关键注意事项
- 用
[weak self]避免循环引用,防止内存泄漏; - 开启TableView自动高度后,输入框内容增多时单元格会自动适配高度;
- 如果不想拆分两个Cell,也可以在一个Cell里同时放置Label和TextView,通过
isHidden属性控制显示状态,但拆分的方式更易维护。
内容的提问来源于stack exchange,提问作者AlexP
相关产品推荐
相关产品推荐

