使用UITableViewDiffableDataSource展示不同对象时仅显示一行的问题求助
Hey there! The issue you're facing is because right now, you're treating an entire array of Company or Member as a single item in your diffable snapshot. That's why only one row shows up—your data source thinks there's just one item to display, even though that item contains multiple entries.
Let's fix this step by step:
1. Adjust the Wrapper enum to represent individual items
Right now, Wrapper wraps an array of objects. We need to change it to wrap a single object instead, so each row in the table corresponds to one Wrapper instance:
enum Wrapper: Hashable { case one(Company) // Now wraps a single Company, not an array case two(Member) // Now wraps a single Member, not an array }
2. Update the data source's cell provider logic
Since each Wrapper now holds a single item, you don't need to use indexPath.row to access elements from an array. You can directly use the wrapped object:
private func configureDataSource() { dataSource = ListDataSource(tableView: listTableView, cellProvider: { [weak self] (_, indexPath, wrapper) -> UITableViewCell? in guard let self = self else { return UITableViewCell() } let cell = self.listTableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) switch wrapper { case .one(let company): cell.textLabel?.text = company.name case .two(let member): cell.textLabel?.text = member.name.first } return cell }) }
3. Rewrite the updateData method to add individual items to the snapshot
Instead of adding one wrapper that contains an entire array, we'll convert each object in your array to a Wrapper and add all of them to the snapshot:
func updateData(with items: [Wrapper]) { var snapshot = ListSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(items) dataSource.apply(snapshot, animatingDifferences: true) }
4. Update the segment control handler to pass individual items
Modify handleSegmentChanged to map your arrays into arrays of Wrapper instances and pass them to updateData:
func handleSegmentChanged(_ sender: UISegmentedControl) { let member = Member(name: Name(first: "Harshal", last: "Wani"), memberId: "123", age: 30, email: "harshal@gmail.com", phone: "123456789") let member2 = Member(name: Name(first: "David", last: "John"), memberId: "123", age: 30, email: "harshal@gmail.com", phone: "123456789") let comp = Company(name: "Comp 1", companyId: "", website: "", logo: "", about: "", members: [member, member2]) let comp2 = Company(name: "Comp 2", companyId: "", website: "", logo: "", about: "", members: [member, member2]) if sender.selectedSegmentIndex == 0 { // Convert each Company to a Wrapper.one instance let companyItems = [comp, comp2].map { Wrapper.one($0) } updateData(with: companyItems) } else { // Convert each Member to a Wrapper.two instance let memberItems = comp.members.map { Wrapper.two($0) } updateData(with: memberItems) } }
That's it! Now when you switch segments, the table view will display one row for each Company or Member in your arrays, instead of a single row containing the whole array.
内容的提问来源于stack exchange,提问作者Harshal Wani

