티스토리 뷰

반응형

 

# 문제

저번글의 예제앱에서 사용한 데이터를 보겠습니다.

var arr = ["Zedd","Alan Walker", "David Guetta", "Avicii", "Marshmello", "Steve Aoki", "R3HAB", "Armin van Buuren", "Skrillex", "Illenium", "The Chainsmokers", "Don Diablo", "Afrojack", "Tiesto", "KSHMR", "DJ Snake", "Kygo", "Galantis", "Major Lazer", "Vicetone"
    ]

 

여기에는 큰 문제가 있습니다. 

var arr = ["Zedd", ✅"Zedd"✅,"Alan Walker", "David Guetta", "Avicii", "Marshmello", "Steve Aoki", "R3HAB", "Armin van Buuren", "Skrillex", "Illenium", "The Chainsmokers", "Don Diablo", "Afrojack", "Tiesto", "KSHMR", "DJ Snake", "Kygo", "Galantis", "Major Lazer", "Vicetone"
    ]

이렇게 “Zedd”를 한번 더 넣게 되면

DiffableDataSource_Example[75856:2941803] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Fatal: supplied item identifiers are not unique.'

이런 에러를 내며 crash가 나게 됩니다. 

 

# 원인

저번 글에서 SectionIdentifierType과  ItemIdentifierType은 Hashable을 준수해야한다고 했습니다.

String은 Hashable을 준수하고 있으므로 ItemIdentifierType으로 들어갈 수 있었죠.

var arr = ["Zedd", ✅"Zedd"✅,"Alan Walker", "David Guetta", "Avicii", "Marshmello", "Steve Aoki", "R3HAB", "Armin van Buuren", "Skrillex", "Illenium", "The Chainsmokers", "Don Diablo", "Afrojack", "Tiesto", "KSHMR", "DJ Snake", "Kygo", "Galantis", "Major Lazer", "Vicetone"
    ]

"Zedd"에 대한 Hash값이 1이라면, 그 다음 "Zedd"에 대한 Hash값도 1입니다.

Diffable datasource는 ItemIdentifier에 대해서 고유한 Hash값을 요구하는데요.

Hash값이 같은것이 있음 ==> identifier가 고유하지 않음 ==> crash

이런 문제가 있는것입니다. 

 

# 개선

supplied item identifiers are not unique.

이게 원인이니 유니크하게 만들어주면됩니다. 즉 다른 Hash값을 가질 수 있도록 해주면 됩니다. 

그럼 

var arr = ["Zedd","Alan Walker", "David Guetta", "Avicii", "Marshmello", "Steve Aoki", "R3HAB", "Armin van Buuren", "Skrillex", "Illenium", "The Chainsmokers", "Don Diablo", "Afrojack", "Tiesto", "KSHMR", "DJ Snake", "Kygo", "Galantis", "Major Lazer", "Vicetone"
    ]

이 친구들이 String으로 되어있는 이상 hashValue uniqueness문제는 항상 발생할 수 있습니다.

그러므로 같은 이름을 가지고 있지만 다른 Hash값이 나올 수 있도록 해보겠습니다. 

 

1. 타입 정의 

[String]으로는 할 수 있는게 없으므로..Custom Type을 만들어주겠습니다. 

struct DJ: Hashable {
    
    var name: String
}

DJ를 만들고 Hashable을 준수해야하므로 Hashable을 준수하도록 해줍니다.

struct DJ: Hashable {
    
    var name: String
}

let zedd1 = DJ(name: "Zedd")
let zedd2 = DJ(name: "Zedd")

자 이렇게 하면, zedd1과 zedd2의 hashValue는 다를까요?

아닙니다. 같습니다.

print(zedd1.hashValue == zedd2.hashValue) // true

DJ타입의 경우 hashValue를 생성하기 위한 프로퍼티가 name하나밖에 없는데, 이게 같으니 hashValue도 같을 수 밖에 없는 것이죠.

name은 같지만, hashValue를 다르게 할 다른 프로퍼티가 필요합니다.

struct DJ: Hashable {
    
    var address: String
    var name: String
}

let zedd1 = DJ(address: "Earth", name: "Zedd")
let zedd2 = DJ(address: "Mars", name: "Zedd")

print(zedd1.hashValue == zedd2.hashValue) // false

이런식인거죠.

하지만 address이런 필요없는(?) 프로퍼티 정의보다 나은 방법이 있습니다.

바로 UUID를 사용하는 것이죠.

 

2. id 프로퍼티 정의

UUID는 타입, 인터페이스 및 기타 항목을 식별하는 데 사용할 수 있는 보편적으로 고유 한 값입니다.

그래서 

struct DJ: Hashable {
    
    let id = UUID()
    var name: String
}

이렇게 id값을 정의해줬습니다.

struct DJ: Hashable {
    
    let id = UUID()
    var name: String
}

let zedd1 = DJ(name: "Zedd")
let zedd2 = DJ(name: "Zedd")

print(zedd1.hashValue == zedd2.hashValue) // false

이렇게 간단하게 hashValue를 다르게 할 수 있습니다.

 

3. ItemIdentifierType바꿔주기 

var dataSource: UICollectionViewDiffableDataSource<Section, String>!

저번 글에서 ItemIdentifierType이 이렇게 String으로 들어가있을텐데, 이런것들을 전부 DJ타입으로 바꿔주면 됩니다.

자세한 변경사항은 github을 참고해주세요.

 

이렇게하면..

Crash안나고 잘 되는 것을 볼 수 있습니다.

 

ㅎㅎ..이걸 저번글에서는 몰랐어가지고...많이 중요한건데 ㅎ ㅏㅎ ㅏ..

반응형

'공부' 카테고리의 다른 글

Carthage  (0) 2021.04.15
Swift ) Quick / Nimble 간단하게 사용해보기  (0) 2021.04.14
Diffable Datasource  (3) 2021.04.06
TextStyle과 UIFontMetrics(with Custom Font)  (0) 2021.04.05
HIG ) Color and Contrast  (0) 2021.04.01