I think there is a problem with the calendar model or the data I put in the pile, but I can't find it no matter how much I look for it. I'm desperate for help
The contents of the error are as follows
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Fatal: supplied item identifiers are not unique. Duplicate identifiers: {(
HomeDataSource.Item.calendar
class HomeDataSource {
typealias DataSource = UITableViewDiffableDataSource<Section, Item>
private let tableView: UITableView
private lazy var dataSource = createDataSource()
private let postType: PostCase
var calendars: [Calendar] = [
Calendar(date: "haha"),
Calendar(date: "hhohoho"),
]
private var posts: [UserPost]
enum Section: CaseIterable {
case calendar
case post
init(rawValue: Int) {
switch rawValue {
case 0: self = .calendar
case 1: self = .post
default:
fatalError("not exist section")
}
}
}
enum Item: Hashable {
case calendar
case post
}
init(tableView: UITableView, postType: PostCase) {
self.tableView = tableView
self.postType = postType
self.posts = .init()
}
func createDataSource() -> UITableViewDiffableDataSource<Section, Item> {
tableView.register(CalendarTableViewCell.self, forCellReuseIdentifier: CalendarTableViewCell.identifier)
tableView.register(UserPostTableViewCell.self, forCellReuseIdentifier: UserPostTableViewCell.identifier)
tableView.register(EmptyPostTableViewCell.self, forCellReuseIdentifier: EmptyPostTableViewCell.identifier)
dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) {
tableView, indexPath, item in
switch item {
case .calendar:
let cell = tableView.dequeueReusableCell(withIdentifier: CalendarTableViewCell.identifier, for: indexPath)
cell.selectionStyle = .none
return cell
case .post:
switch self.postType {
case .postExist:
guard let cell = tableView.dequeueReusableCell(withIdentifier: UserPostTableViewCell.identifier, for: indexPath) as? UserPostTableViewCell else { return UITableViewCell() }
cell.selectionStyle = .none
cell.configure()
return cell
case .friendPostEmpty:
guard let cell = tableView.dequeueReusableCell(withIdentifier: EmptyPostTableViewCell.identifier, for: indexPath) as? EmptyPostTableViewCell else { return UITableViewCell() }
cell.configure(isFriend: true)
return cell
case .ownerPostEmpty:
guard let cell = tableView.dequeueReusableCell(withIdentifier: EmptyPostTableViewCell.identifier, for: indexPath) as? EmptyPostTableViewCell else { return UITableViewCell() }
cell.configure(isFriend: false)
return cell
}
}
}
return dataSource
}
func updateSnapshot(posts: [UserPost]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.calendar, .post])
let calendarIds = calendars.map { _ in Item.calendar }
let postIds = posts.map { _ in Item.post }
snapshot.appendItems(calendarIds, toSection: .calendar)
snapshot.appendItems(postIds, toSection: .post)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
Calendar model is as follows
struct Calendar: Hashable {
let id = UUID()
let date: String
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Calendar, rhs: Calendar) -> Bool {
lhs.id == rhs.id
}
init(date: String) {
self.date = date
}
}
Also, I would like to ask you additionally what should I do if I want to put only one value in the snapshot data?
The problem is here:
You just map all the different models into equal Item. Any
Calendar
with uniqueid
turns intoItem.calendar
which have noid
. All of them are equal.if you still want to us
enum
then I suggest you declare it like that:This should help you.
Moreover, as
vadian
mentioned, you better not useCalendar
. Rename it toUserCalendar
for example.