KVO 기본 원리와 수동 실현

3242 단어
Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.
KVO는 피관찰 대상이 바뀔 때 관찰자가 통지를 받지만 KVO를 사용한 친구들은 우리가 피관찰 대상에 코드를 쓸 필요가 없다는 것을 안다.그렇다면 KVO는 어떻게 속성을 감청합니까?

KVO 원리


먼저 공식 문서를 살펴보겠습니다.
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ...
애플은 KVO 구현에 이사-swizzling 기술이 사용됐다고 밝혔다.
KVO를 사용하여 대상을 관찰할 때, 새로운 클래스가 실행될 때 생성됩니다.이 클래스는 대상의 원래 클래스를 계승하고 관찰된 속성의setter 방법을 다시 썼다.다시 쓰는 setter 방법은 원래의 setter 방법을 사용하기 전과 후에 모든 관찰자에게 통지하는 것을 책임진다.그리고isa-swizzling을 통해 이 관찰 대상의 **isa 지침을 새로 만든 하위 클래스 **를 가리키며 관찰 대상은 이렇게 새로 만든 하위 클래스의 실례가 되었다.
하나의 속성의 값이 바뀔 때setter 방법이 호출되기 때문에 관찰자에게 이 일이 속성의setter 방법에 발생했음을 알려줍니다.사실 키 값 관찰 알림은 NSObject의 두 가지 방법에 의존한다. willChangeValueForKey:didChangevlueForKey:.관찰된 속성이 바뀌기 전에 willChangeValueForKey: 먼저 호출되고 이 방법은 낡은 값을 기록하는 것을 책임진다.변화가 발생하면 observeValueForKey:ofObject:change:context:가 호출되고 마지막에 호출된다didChangeValueForKey:.
위조 부호 표시:
- (void)setFoo:(id)foo
{
    [self willChangeValueForKey];
    _foo = foo;
    [self observeValueForKey:key ofObject:target change:CHANGE context:nil];
    [self didChangeValueForKey];
}

이것은 또한 "직접 접근"(예:self.foo 대신 foo) 을 통해 속성 값을 설정하는 것이 KVO를 터치하지 않는다는 것을 의미한다.
이 밖에setter가 다시 쓴 것 외에 애플은 -class를 다시 써서 원래 속했던 클래스로 되돌려주었다. 예를 들어 [foo class]는 새로 만든 하위 클래스가 아니라 원래 속했던 클래스로 되돌려주었다.
또한 KVO의 밑바닥을 파헤쳐 실행할 때 Mike Ash의 이 글을 추천합니다.

KVO 결함


KVO에 관한 많은 논쟁이 존재하고 있습니다. NSHipster, KVO Considered Harmful과Key-Value Observing Done Right를 보십시오.
KVO의 문제점은 다음과 같습니다.
  • API 설계 결함.NSNotification의 API는 selector(-addObserver:selector:name:object:)를 전송하여 알림을 받을 때 selector로 호출할 수 있도록 합니다.반대로 KVO를 사용하면 관찰자 클래스에서 -observeValue ForKeyPath:ofObject:change:context:방법을 다시 써야 합니다. 우리는 이 방법에 판단 논리를 많이 넣어서 서로 다른 속성을 감청해야 합니다.
  • -addObserver:forKeyPath:options:context:에 NSString 대상을 키Path로 전송하면 컴파일러는 오류를 감지할 수 없습니다. 속성 이름이 바뀌면 이 관찰은 의미가 없습니다.이 문제는 NSStringFromSelector를 통해 약간 개선할 수 있습니다.또한 context에 전달되는 매개 변수는 대부분 nil입니다.
  • 만약에 부류와 자류가 같은 대상의 같은 속성을 감청하면 부류에서remove를 한 번 하고 자류가remove를 한 번 하는 상황이 발생하기 쉽다. 응용 프로그램이 두 번째remove를 하면 이상을 던지고crash.솔루션은 KVO Considered Harmful을 참조하십시오.
  • KVO는 사순환을 초래할 수 있습니다.사순환이 발생하는 장면은 다음과 같다. -observe Value ForKey Path 방법에 속성을 설정했는데, 이 속성은 마침 자신이 감청했다.
  • 일부 상황에서 KVO 스니퍼 속성을 사용하면 비활성화됩니다.예를 들어 감청 속성의setter가 훅에 걸렸다.또 다른 상황은 weak 속성에 대한 감청이다. 만약에 weak 실례 변수가 가리키는 대상이 방출되면 weak 수식의 실례 변수는 자동으로 nil로 설정되고 KVO도 효력을 상실한다.

  • 구덩이가 많으니 KVO는 특히 조심해야 한다.

    KVO 수동 구현


    KVO에서 사용할 때 주의해야 할 점이 많은데 귀찮으면 우리가 직접 훑어보고 놀 수 있다.아이디어를 실현하려면 글로우 팀의 이 글을 볼 수 있고 나는 벽돌을 옮기지 않을 것이다.비슷한 사고방식을 바탕으로 저는 selector 매개 변수를 전달할 수 있는 KVO를 실현했습니다.데모가 내 github 위에 놓여 있어.
    참고 기사: How Key-Value Observing is actually implemented at the runtime level KVO KVO Considered Harmful Key Value Observing Key-Value Observing Done Right Creating Classes at Runtime in Objective-C Associated Objects

    좋은 웹페이지 즐겨찾기