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

如何解决UITableView单元格内签名视图重复显示问题

解决UITableView单元格复用导致签名视图重复的问题

问题核心

你的问题根源在于错误复用了签名视图实例,而非在单元格复用时正确重置/恢复签名数据。当前代码直接将SamsoSignatureView实例存入数组并复用,导致滚动时同一个视图被多个单元格引用,最终出现签名串位的情况。

正确解决方案

核心思路:不存储签名视图实例,只存储每个行对应的签名数据(如pathArray),单元格复用时根据数据重置视图内容,而非替换视图本身。

1. 修改数据模型

只保留签名数据,移除视图实例的存储:

struct SignatureData {
    let row: Int
    var pathArray: NSMutableArray?
}

2. 重写单元格的prepareForReuse

在ProfileSignataureTableViewCell中添加该方法,确保复用前清空旧签名:

class ProfileSignataureTableViewCell: UITableViewCell {
    // 你的其他控件定义
    
    override func prepareForReuse() {
        super.prepareForReuse()
        // 重置签名视图状态
        signatureView?.pathArray = NSMutableArray()
        // 如果签名视图有自带的清空方法,也可直接调用:
        // signatureView?.clearSignature()
    }
}

3. 修正cellForRowAt逻辑

不再存储视图实例,改为根据数据恢复签名内容:

// 全局存储签名数据的数组
var signatureDataArray: [SignatureData] = []

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cellReusableId = String(describing: ProfileSignataureTableViewCell.self)
    
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReusableId, for: indexPath) as? ProfileSignataureTableViewCell else {
        fatalError("Cell not exists in storyboard")
    }
    
    // 设置控件代理与tag
    cell.firstNameText.delegate = self
    cell.lastNameText.delegate = self
    cell.ageText.delegate = self
    cell.firstNameText.tag = indexPath.row
    cell.lastNameText.tag = indexPath.row
    cell.ageText.tag = indexPath.row
    cell.signatureView?.delegate = self
    cell.signatureView?.tag = indexPath.row
    
    // 恢复当前行的签名数据
    if let existingData = signatureDataArray.first(where: { $0.row == indexPath.row }) {
        cell.signatureView?.pathArray = existingData.pathArray ?? NSMutableArray()
    } else {
        // 无数据则清空(prepareForReuse已处理,此处做双重保障)
        cell.signatureView?.pathArray = NSMutableArray()
    }
    
    // 绑定清空按钮
    cell.btn_clear.tag = indexPath.row
    cell.btn_clear.addTarget(self, action: #selector(editButtonPressed), for: .touchUpInside)
    
    return cell
}

4. 保存签名数据

在签名完成的代理方法中(根据你的SamsoSignatureView实际代理调整)更新数据:

// 示例代理方法,以你的实际回调为准
func signatureViewDidFinishSigning(_ signatureView: SamsoSignatureView) {
    let row = signatureView.tag
    // 更新已有数据或新增数据
    if let index = signatureDataArray.firstIndex(where: { $0.row == row }) {
        signatureDataArray[index].pathArray = signatureView.pathArray
    } else {
        signatureDataArray.append(SignatureData(row: row, pathArray: signatureView.pathArray))
    }
}

5. 处理清空按钮逻辑

@objc func editButtonPressed(sender: UIButton) {
    let row = sender.tag
    // 删除对应行的签名数据
    if let index = signatureDataArray.firstIndex(where: { $0.row == row }) {
        signatureDataArray.remove(at: index)
    }
    // 刷新对应行,确保视图更新
    tableView.reloadRows(at: [IndexPath(row: row, section: 0)], with: .automatic)
}

原方案失效原因

  1. 直接存储SamsoSignatureView实例,导致同一个视图被多个单元格引用,滚动时视图在不同单元格间迁移,造成签名串位。
  2. 即使尝试恢复pathArray,视图实例的复用会导致绘制状态混乱,因为视图本身是同一个对象,不同单元格的显示会互相影响。

内容的提问来源于stack exchange,提问作者vladislav.samsotech

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:45:06