stirng, integer, floating-point, boolean values, set이 기본적으로 hash value를 제공하며(이때 set은 hashable한 것만 들어갈 수 있다) 자신만의 사용자 정의 타입도 hash가 가능할 수 있다. associated valuew없이 열거형(enum)을 정의하면, hashable 준수가 자동으로 적용되고, hash value 프로퍼티를 추가해 사용자 정의 타입에 hashable 준수를 추가할 수도 있다.
타입의 hash value 프로퍼티에 의해 제공되는 hash값은 동일하게 비교되는 임의의 두 인스턴스에 대해 동일한 정수이다.
즉, 같은 타입의 인스턴스인 a와 b의 경우 a==b이면 a.hashvalue == b.hashvalue가 된다는 것을 의미한다.
그러나 반대의 경우에는 true가 아닐 수도 있다. 동일한 hash값을 가진 두개의 인스턴스가 서로 동일할 필요는 없기 때문이다.
hash 값은 프로그램 실행에 따라 동일하지 않을 수 있다. 향후 실행에 사용할 hash값을 저장하지 않아야 한다
Conforming to the Hashable Protocol
set은 hashable한 것만 들어갈 수 있으며 dictionary의 key역시 hashable하다고 했다.
사용자 정의 타입을 set에 넣거나 dictionary key로 만들고 싶다면 타입이 hashable을 준수하면 된다.
사용자 정의 타입의 hashable과 equatable 요구사항은 타입이 다음 조건을 충족시킬 때 컴파일러에서 자동으로 합성(synthesized)해준다.
구조체의 경우, 저장 프로퍼티는 모두 hashable을 준수해야 한다.
열거형의 경우, 모든 associated values은 모두 hashable을 준수해야 한다.
associated values가 없는 열거형은 정의없이(hash value) hashable을 준수한다.
타입의 hashable 준수를 커스터마이즈하거나, 위에서 말한 기준에 맞지 않는 형식으로 hashable을 채택하거나, 또는 이미 존재하는 타입을 hashable 준수하도록 확장하는 경우에는 사용자 지정 타입에 hashvalue 프로퍼티를 구현한다. 타입이 hashable 및 equatable 프로토콜의 의미론적 요구사항(semetic requirements)을 충족시키려면 타입의 equatable 준수를 사용자 정의하여 일치시키는 것이 좋다.
예 - 버튼 그리드의 위치
버튼 그리드의 위치를 설명하는 GridPoint 타입을 보자. GridPoint의 초기선언은 아래와 같다.
structGridPoint{varx:Intvary:Int}
이제 여기서 사용자가 탭한 grid point의 set을 만들고 싶다고 가정해보자.
GridPoint타입은 아직 해시가능하지 않기에, set의 element 타입으로 사용할 수 없다.
hashable을 준수하려면 == 연산자와 hashvalue 프로퍼티를 제공해야하기 때문이다.
즉 hashValue를 만들어주지 않았음에도 불구하고 컴파일러가 자동으로 만들어준 것이다. 이게 가능한 이유는
/// A point in an x-y coordinate system.structGridPoint:Hashable{varx=Intvary=Int}
GridPoint타입의 저장프로퍼티가 모두 hashable한 값들이기 때문이다.(구조체의 경우~~~)
따라서 hashable 프로토콜을 사용자 정의 타입에서 채택만 하면 이제 set에 들어갈수도 dictionary의 key로도 들어갈 수 있음을 의미한다.
Set, Dictionary key가 되려면 왜 hashable 해야할까?
해시함수는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다.
이 용도중 하나로는 해시테이블이라는 자료구조에 사용되며 매우 빠른 데이터 검색을 위한 컴퓨터 소프트웨어에 널리 사용된다.
해시 함수는 큰 파일에서 중복되는 레코드를 찾을 수 있기에 데이터베이스 검색이나 테이블 검색 속도를 가속할 수 있다.
즉, swift의 set과 dictionary key에는 순서가 없다. hashable의 정의가 “정수 hash값을 제공하는 타입” 인데 이 정수 hash가 있기 때문에 우리가 찾으려는 원소를 더 빨리 찾을 수 있게 되는 것이다.
즉, Equatable이라는 약속이 있다는 것을 의미하며, 이를 채택하면 이를 준수해야한다는 것이다.
A type that can be compared for value equality.
값이 동일한 지 어떤지를 비교할 수 있는 타입
즉, Equatable 프로토콜을 준수하는 타입은 등호 연산자(==) 또는 같지 않음 연산자(!=)를 사용해 동등성을 비교할 수 있다. swift 표준 라이브러리의 대부분 기본 데이터타입은 Equatable을 따른다. 따라서 Equatable 프로토콜은 어떤 타입이 채택하는 것으로 이때 타입에는 클래스, 구조체, 열거형 등이 있을 것이다.
뿐만 아니라 Int, String, Double, Boole 등 기본적인 데이터타입도 Equatable을 따르고 있다.
Delegation, Notification center, KVO는 iOS를 만들다보면 자주 나오는 패턴들이다. KVO를 제외하면 실제 매우 자주 사용해본 경험도 있을 것인데, 대부분의 경우 View와 VC 간 또는 각각의 것들 사이에서 소통이 필요할 때 사용했을 것이다. 어떤 이벤트가 A에서 발생하면 B에 알려주어 적절한 조치를 취하도록 하는 것.
그렇다면 이 세가지 패턴은 왜 만들어지게 되었을까?
하나의 객체가 다른 객체와 소통은 하되 묶이기(coupled)는 싫어서..
세 패턴 모두 특정 이벤트가 일어나면 원하는 객체에 알려주어 해당되는 처리를 하는 방법을 가지고 있다. 어플리케이션의 특성 상 객체 간 소통은 필수적이다. 하지만 한 객체는 그 자체로 존재하면서 소통하고 싶을 뿐 다른 객체에 종속되어 동작하는 것은 재사용성 과 독립된 기능 요소 측면에서 바람직하지 않다. 대표적으로 VC는 한 View를 관리하는 독립적인 객체로 존재해야지 소통을 위해 다른 VC에 묶여 동작하는 것은 올지 않은 방식이다. 따라서 이때 Delegation, Notification, KVO를 사용한다.
Delegation
Delegate은 보통 프로토콜을 정의하여 사용한다. Protocol이란 일종의 기능 명세서 같은 것으로 Delegate로 지정된 객체가 해야 하는 메소드들의 원형을 적어 놓는다. Delegate 역할을 하려는 객체는 이 Protocol을 따르며 원형만 있던 메소드들의 구현을 한다. 이렇게 세팅 후 이전 객체는 어떤 이벤트가 일어났을 시 delegate로 지정한 객체에 알려줄 수 있다.