Swift 4 에서 KVO ​사용해보기

Swift 4 부터는 KVO (Key-Value Observing) 를 쓰기가 이전보다 약간 더 편해질 예정이다.

우선 Swift 4 의 변화점 중에 키패스 표기법의 변화를 알아야 하는데 그건 아래 글에서 참고하자.

[링크] 눈에 띄는 Swift 4 변경점들 (Xcode 9 첫 Beta 기준)

간단하게 정리하자면 키패스를 아래 처럼 쓸 수 있게 되었다.
\.name
너무 생략한 것 같지만 사실이다. -_-;

다짜고짜 예제

KVO의 개념이나 기본적인 사용법은 앞서 적은 글에 있으니 생략하고, 다짜고짜(?) 예제 코드부터 보자. 아래 코드는 특정 클래스의 프로퍼티(value)의 변화를 추적하기 위한 예제이다.
class SomeClass: NSObject {
  @objc dynamic var value: String = ""
}

let someObject = SomeClass()

someObject.observe(\.value) { (object, change) in
  print("SomeClass object value changed to \(object.value)")
}

someObject.value = "test"  // TEST
여기서는 NSObject 를 상속받은 SomeClass 클래스를 정의하고 있다. NSObject 는 KVO 지원을 위해서는 필수다. KVO 기능은 NSObject 에 구현되어 있기 때문이다. 이는 당연하기도 하고 이전(Swift 3.x 혹은 그 이전)과 동일하다.

유일한 프로퍼티인 value 앞에는 dynamic 이라는 수식어가 붙어있는데 dynamic dispatch 를 활성화 시키는 오퍼레이터다. 간단(?)하게 언급하자면 키패스(KeyPath) 이름을 이용해 프로퍼티의 주소를 찾게 해 주도록 하라는 정도라고 할 수 있을 것 같다.

그런데 dynamic 앞에는 @objc 가 붙어있는데 이는 현재 Swift 4 (Xcode 9 Beta 3 기준) 에서 dynamic 의 제약사항이다. 즉 dynamic 앞에는 무조건 @objc 가 와야한다. 하여간, 이 @objc 는 이전과 동일하게 Objective-C 호환성을 만들어 줄 수 있다.

핵심적인 부분은 옵저버를 심기 위한 observe() 메소드이다. 이 observe() 메소드는 기존 3.x 버전들과는 다르게 클로져를 이용할 수 있게 추가된 메소드다. 즉 해당 오브젝트에서 키패스로 지정된 프로퍼티의 값이 바뀌게 되면 클로져가 호출되게 된다. 귀찮게 오버라이드를 쓸 필요가 없어졌다. 심지어 컨텍스트 같이 몰라도 되는 값은 아예 보이지 않게 되었다. 이 부분은 정말 Swift 친화적으로 바뀌었다.

하여간 예제의 observe() 명령으로 someObject 의 value 라는 프로퍼티의 변화를 감지하기 시작한다. 결과적으로 마지막 줄에서 someObject.value 값을 바꾸자마자 "SomeClass object value changed to test" 라는 로그가 콘솔에 찍히게 된다.

@objcMembers

만약 변화를 추적할 프로퍼티가 많은데 그 앞에 전부 @objc 라는 키워드를 붙이는게 낭비(?) 같거다 귀찮다면 @objcMembers 라는 키워드를 이용해 볼 수 있다.

@objcMembers 를 이용하면 위 SomeClass 클래스 코드를 아래처럼 단순화 시킬 수 있다.
@objcMembers class SomeClass: NSObject {
  dynamic var value: String = ""
  dynamic var anotherValue: Int = 0
  …
}
(아니 뭐 사실 크게 단순화 된 것 같진 않지만 그냥 넘어가자 -_-;;;)

위 예제는 앞서 본 예제와는 다르게 dynamic 앞에 @objc 가 붙어있지 않다. 대신 class 앞에 @objcMembers 라는 키워드가 붙어있다.

이 @objcMembers 는 @objc의 광역버전(?)이라고 볼 수 있다. 모든 멤버들에게 Objective-C 호환성 버프를 걸어준다고나 할까.

마무리

이제 KVO 를 Swift 에서 쓰기에 문법상으로 무리는 약간 없어졌다고 보인다. 하지만 NSObject 를 상속받아야 되는 문제는 여전한데, 이는 KVO 라는 개념 자체가 여기서부터 출발하다보니 어쩔 수 없는 문제일지도 모르겠다.

애플과 오픈소스 커미터 분들이 힘내서 순수 Swift ​방식의 KVO 와 비슷한 기능을 개발해 줬으면 좋겠다.

[관련글] KVO (Key-Value Observing) 소개
[관련글] 눈에 띄는 Swift 4 변경점들 (Xcode 9 첫 Beta 기준)
[관련글] 스위프트(Swift) 가이드
[관련글] Core Foundation Resources

댓글

이 블로그의 인기 게시물

버전(Version)을 제대로 이해하기

소수점 제거 함수 삼총사 ceil(), floor(), round()