【Swift 4.2】 【Swift 5】 Hashable과 Codable과 상속을 동시에 사용하면 hashValue의 참조로 충돌한다
【개요】
Swift 4.2/5.0에서 Hashable과 Codable과 상속을 동시에 사용하면 hashValue 참조로 충돌합니다.
【환경】
let lang = "Swift 4.2"+ "Swift 5.0"
let env="XCode10"+ "XCode10.2"
【상세 내용】
먼저 Swift 4.2에서 도입된
func hash(into hasher: inout Hasher)
를 사용하여 Hashable을 구현합니다.ただし、下記のクラスはテストファイル中ではなく、アプリ内のファイル(アプリバンドルない)に記述します。(2019/3/30更新)
open class HashableTestModel: Hashable
{
public var uniqueIdentifier: String
public init()
{
self.uniqueIdentifier = String(arc4random())
}
// Equatable
static public func ==(lhs: HashableTestModel, rhs: HashableTestModel) -> Bool
{
return true
}
public func hash(into hasher: inout Hasher)
{
hasher.combine(uniqueIdentifier)
}
}
↑ 여기까지는 문제 없습니다. 그런 다음 HashableTestModel을 Codable로 설정합니다.
open class HashableTestModel: Hashable, Codable
{
또한 HashableTestModel을 상속한 HashableTestModelChild를 만듭니다.
HashableTestModelChild는 공백으로 남을 수 있습니다.
open class HashableTestModelChild: HashableTestModel
{
}
이제 테스트합니다.
func testCoreModelHashable() {
let val = HashableTestModel()
print(val.hashValue)
}
충돌합니다.
Codable을 중지하거나 상속을 중지하면 작동합니다.
또 문제가 되고 있는 클래스를 테스트 파일내에 기술하면 동작합니다.
신기하네요.
일반적으로 두 코드 모두 앱의 메인 번들에 작성되어야하므로 문제가 발생하지 않습니다. 테스트에서는 죽지만.
문제는 Embedded Framework를 사용하고 호출자와 해당 클래스의 번들이 다른 경우입니다. (실제 내 테스트에서 메인 번들에서 Embedded Framework 위의 클래스를 호출하는 것처럼 충돌했습니다.
【더 알게 된 것】
베이스 클래스를, 다른 번들(Embedded Framework내 등)에 두고,
상속 클래스를 메인 번들에 넣은 상태에서 인스턴스를 만들고
print(val.hashValue)
를 실행하면 충돌하지 않습니다.open class HashableTestModelChild: HashableTestModel
만들 때 기본 클래스 public func hash(into hasher: inout Hasher)
{
hasher.combine(uniqueIdentifier)
}
불리지 않습니다.
【샘플 코드】
샘플 코드는 여기에 넣었습니다.
6월에 WWDC에 가서 애플의 엔지니어에게 직접 들어보자고 생각합니다.
【해결했습니다】
open class HashableTestModel_Other: Codable
{
public var uniqueIdentifier: String
public init()
{
self.uniqueIdentifier = String(arc4random())
}
// Equatable
static public func ==(lhs: HashableTestModel_Other, rhs: HashableTestModel_Other) -> Bool
{
return true
}
}
extension HashableTestModel_Other: Hashable
{
public func hash(into hasher: inout Hasher)
{
hasher.combine(uniqueIdentifier)
}
}
open class HashableTestModelChild_Other: HashableTestModel_Other
{
}
이와 같이, Hashable을 extension으로 기술하면 크래시하지 않는 것을 알았습니다.
Reference
이 문제에 관하여(【Swift 4.2】 【Swift 5】 Hashable과 Codable과 상속을 동시에 사용하면 hashValue의 참조로 충돌한다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/BlueEventHorizon/items/065ebda3b9391325f24d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)