UIKit中嵌套UITableView滚动后数据显示错误问题求助
修复嵌套UITableView滚动数据错乱的问题
1. 修正API请求中的数据源赋值错误
你的API请求中存在变量名不匹配、memberArray未填充的问题,导致主TableView数据源不一致。修改数据处理逻辑,同步填充两个核心数据源:
func getAllBookings() { var urlRequest = URLRequest(url: URL(string: "mylistUrl")!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10) urlRequest.headers = APINetworkClass.shared.getHeader() urlRequest.httpMethod = "GET" URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in if let error = error { print(error) return } guard let data = data, let _ = response as? HTTPURLResponse else { return } do { let bookingArray = try JSONDecoder().decode(BookingRevamp.self, from: data) var testResults: [[[String]]] = [] var memberSectionResults: [[String]] = [] for result in bookingArray.results { let packages = result.packages.map(\.name) let additionalMembers = result.additionalMembers.flatMap(\.packages).map(\.name) // 填充memberArray:生成主成员/额外成员的标题数组 var sections: [String] = ["主成员"] if !additionalMembers.isEmpty { sections.append("额外成员") } memberSectionResults.append(sections) // 填充测试包数据 testResults.append(additionalMembers.isEmpty ? [packages] : [packages, additionalMembers]) } // 修正变量名匹配,同步更新两个数据源 self.memberArray = memberSectionResults self.memberTestsArray = testResults } catch { print("解析错误==>>", error) } DispatchQueue.main.async { self.bookingListTableview.reloadData() } }.resume() }
2. 修复自定义Cell的复用逻辑
UITableViewCell复用会残留旧数据,必须在prepareForReuse中完全重置数据源并刷新子TableView:
var sectionArray = [String]() { // 添加属性观察者,赋值后立即刷新子TableView didSet { bookingViewMembersTableview.reloadData() } } var memberTestPackageArray = [[String]]() { didSet { bookingViewMembersTableview.reloadData() } } @IBOutlet weak var bookingViewMembersTableview: UITableView! override func awakeFromNib() { super.awakeFromNib() bookingViewMembersTableview.delegate = self bookingViewMembersTableview.dataSource = self self.bookingViewMembersTableview.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) } override func prepareForReuse() { super.prepareForReuse() // 重置所有UI组件 idLabel.text = "" statusLabel.text = "" dateTimeLabel.text = "" amountLabel.text = "" viewBookingLabel.text = "" // 清空子TableView数据源并强制刷新 sectionArray = [] memberTestPackageArray = [] bookingViewMembersTableview.reloadData() } // 移除观察者避免内存泄漏 deinit { bookingViewMembersTableview.removeObserver(self, forKeyPath: "contentSize") }
3. 确保主TableView数据源一致性
主TableView的section数量需与实际数据源数量保持一致,避免数据越界或不匹配:
func numberOfSections(in tableView: UITableView) -> Int { // 使用实际数据源的数量替代listArray的计数,保证一致性 return memberArray.count }
4. 优化子TableView高度计算逻辑
保留KVO监听内容尺寸的逻辑,确保子TableView高度动态更新时,主TableView能同步刷新布局:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "contentSize" { guard let tableView = object as? UITableView else { return } // 更新子TableView的高度约束 tableView.constraints.forEach { constraint in if constraint.firstAttribute == .height { constraint.constant = tableView.contentSize.height } } // 触发布局更新,让主TableView重新计算单元格高度 self.layoutIfNeeded() self.superview?.layoutIfNeeded() } }
核心问题总结
- UITableView复用机制导致旧数据残留,未在
prepareForReuse中完全重置数据源 - API请求中变量名不匹配、
memberArray未填充,导致数据源不一致 - 子TableView未在数据源更新时及时调用
reloadData() - 主TableView的section数量与实际数据源数量不同步
内容的提问来源于stack exchange,提问作者Abhishek kumar
相关产品推荐
相关产品推荐

