XLOG

Fatal error: Duplicate keys of type 'Node' were found in a Dictionary 해결 본문

Swift

Fatal error: Duplicate keys of type 'Node' were found in a Dictionary 해결

X_PROFIT 2024. 8. 16. 18:44

사이드 프로젝트를 진행하면서 Tree 형태의 데이터 구조를 만들어 사용했다.

데이터는 SwiftData 를 사용해서 저장을 했으며 Model 은 Hashable 을 상속시켰다.

그런데 데이터를 수정하고 나서 한번씩 Fatal error 가 발생했다.

테스트를 더 해보긴 해야겠지만 찾아본 바로 원인은 Hashable을 충족하기 위해서 Equatable 또한 상속시켜야 한다. Hashable 이 Equatable 을 상속해야하는 이유는 HashValue 의 비교를 위해서인데, 여기서 내가 실수한 부분은 == 에 정의할 때 비교 연산을 Hash 함수에 사용한 Propertie 와 달라서 였다.

예를 들면

class Model {
	let id: UUID = UUID()
    let name: String
    let something: CustomStruct
}

extension Model: Equatable {
	static func == (lhs: Model, rhs: Model) -> Bool {
    	lhs.id == rhs.id
    }
}

extension Model: Hashable {
	func hash(into hasher: inout Hasher) {
    	hasher.combine(id)
        hasher.combine(something)
    }
}

 

Model 객체에서 hashValue 는 id와 something 이란 프로퍼티로 생성을 하고 == 는 id 만 가지고 비교를 하기 때문이다.

에러 메시지를 확인해보면 Hashable 프로토콜을 준수하지 못했거나, dictionary 의 변화때문이라고 한다. Model 의 something 프로퍼티가 바뀌고, 그로인해  hashValue 가 달라졌지만 기존 데이터에 같은 값으로 인식할 수 있는 id 값이 이미 존재하기 때문이지 않을까 싶다.

이 문제의 해결법은 hashValue 를 만들때 사용하는 propertie 와 equatable 을 충족시키기 위해 사용하는 비교에 사용하는 propertie 를 똑같게 하면 된다.

사실 Hashable 을 상속할땐 Equatable 도 충족시켜야 한다는 걸 알고는 있었다. 하지만 왜 그래야 하는지에 대한 고민을 하지 않았고, 급하다고 아무 생각없이 모델 구조를 정의했다. 사이드 프로젝트고 아직 출시를 하지 않고 테스트 플라이트를 배포하여 테스트하면 발견한 에러였기에 문제는 없었다. 내가 쓰는 기능들에 대한 의문을 갖으면서도 구현하고 동작시키는 걸 우선시 하다보면 왜인지에 대한 이유를 찾기 소홀해 진다. 이런 작은 차이로 앱의 사용성이 떨어진다는 걸 알면서도....그래도 사이드 프로젝트를 진행하면서 여러 경험을 하고 그로 인해 놓쳤던 부분들까지 신경을 쓸 수 있게 되는 것 같다.

참고 : https://forums.developer.apple.com/forums/thread/726582

'Swift' 카테고리의 다른 글

[Swift] CoreData  (0) 2024.06.08
[Swift] IAP, 인앱결제 StoreKit2  (2) 2024.05.19
[Swift] Concurrency  (0) 2024.05.19