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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:05:54