KVO 원리 분석

5657 단어

개술

KVO은 전칭 KeyValueObserving으로 키값 관찰로 번역된 애플이 제공한 이벤트 알림 메커니즘이다.대상이 다른 대상의 특정한 속성 변화를 감청하고 변경할 때 이벤트를 받을 수 있도록 합니다.KVO의 실현 메커니즘으로 인해 속성에 작용이 발생한다. 일반적으로 NSObject에서 계승된 대상은 모두 KVO을 기본적으로 지원한다.KVONSNotificationCenter은 모두 iOS에서 관찰자 모델의 일종의 실현이다.차이점은 피관찰자와 관찰자 간의 관계에 비해 KVO은 일대일이지 일대일이 아니라는 점이다.KVO은 피감청 대상에 침입성이 없고 내부 코드를 수정하지 않아도 감청을 실현할 수 있다.KVO은 단일 속성의 변화도 감청할 수 있고 집합 대상의 변화도 감청할 수 있다.KVCmutableArrayValueForKey: 등 방법을 통해 대리 대상을 얻고 대리 대상의 내부 대상이 바뀔 때 KVO의 감청 방법을 되돌린다.집합 대상은 NSArrayNSSet이다.

기본 사용


KVO를 사용하려면 다음 세 단계로 나뉘어야 합니다.
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context

1. addObserver:forKeyPath:options:context: 방법으로 관찰자를 등록하면 관찰자는 keyPath 속성의 변화 사건을 수신할 수 있다.2. 관찰자 중에서 observeValueForKeyPath:ofObject:change:context: 방법을 실현하고 keyPath 속성이 바뀌면 KVO은 이 방법을 조정하여 관찰자에게 통지한다.3. 관찰자가 감청을 필요로 하지 않을 때 removeObserver:forKeyPath: 방법으로 KVO을 제거할 수 있다.주의해야 할 것은 removeObserver을 호출하려면 관찰자가 사라지기 전에 해야 한다. 그렇지 않으면 Crash을 초래할 수 있다.

등록 방법

  • 은 관찰자를 등록할 때options 파라미터를 전송할 수 있으며 파라미터는 하나의 매거 유형이다.NSKeyValueObservingOptionNewNSKeyValueObservingOptionOld이 들어오면 새 값과 낡은 값만 받는다고 표시되며, 기본값은 새 값만 받는다.관찰자 등록 후 즉시 리콜을 한 번 받으려면 NSKeyValueObservingOptionInitial 매거진에 가입할 수 있다.
  • 은 방법 context을 통해 임의의 유형의 대상을 전송할 수 있으며 메시지 리셋을 받는 코드에서 이 대상을 수신할 수 있으며 KVO의 일종의 전치 방식이다.
  • addObserver 방법을 사용한 후 KVO은 관찰자를 강제로 인용하지 않기 때문에 관찰자의 생명주기에 주의해야 한다. 그렇지 않으면 관찰자가 석방되어 가져오는 Crash을 초래할 수 있다.

  • 감청 방법

  • 관찰자는 observeValueForKeyPath:ofObject:change:context: 방법을 실현해야 한다. KVO 사건이 발생했을 때 이 방법을 사용하지만 실현되지 않으면 Crash을 초래할 수 있다.change 사전에 KVO 속성과 관련된 값을 저장하고 options에 전송된 매거진에 따라 되돌려줍니다.매거진은 해당 키에 대응하여 사전에서 값을 꺼냅니다. 예를 들어 NSKeyValueChangeOldKey 필드가 있는데, 변경 전의 옛 값을 저장합니다.
  • change에는 NSKeyValueChangeKindKey 필드가 있고 NSKeyValueChangeOldKey과 같은 등급의 관계로 이번 변경에 대한 정보를 제공합니다. NSKeyValueChange의 매거 유형인 value에 대응합니다.예를 들어 관찰된 속성이 바뀌었을 때 필드는 NSKeyValueChangeSetting이다.
  • 관찰 대상이 집합 대상이라면 NSKeyValueChangeKindKey 필드에 NSKeyValueChangeInsertion, NSKeyValueChangeRemoval,'NSKeyValueChangeReplacement의 정보를 포함하여 집합 대상의 조작 방식을 나타낸다.

  • 실제 응용

    KVO은 주로 키 값 관찰 조작을 하는데 한 값이 바뀌면 다른 대상에게 알리려면 KVO으로 하는 것이 가장 적합하다.KVO를 통해 Model과 Controller 간에 통신합니다.

    주의점

  • KVOaddObserverremoveObserver은 짝을 지어야 한다. remove을 반복하면 NSRangeException 유형의 Crash을 초래하고 remove을 잊어버리면 관찰자가 석방된 후에 다시 KVO를 받을 때 Crash이다.
  • 애플의 공식 추천 방식은 init에서 addObserver, dealloc에서 removeObserver으로 addremove이 짝을 지어 나타나는 이상적인 사용 방식이다.

  • KVO 수동 호출

    - (void)willChangeValueForKey:(NSString *)key
    - (void)didChangeValueForKey:(NSString *)key
    

    이 가능하다, ~할 수 있다,...이때 KVO 알림을 자동으로 생성한 다음에 수동으로 호출해야 한다. 수동 알림의 장점은 자신이 원하는 판단 조건을 유연하게 추가할 수 있다는 것이다.다음 예는 다음과 같습니다.
    - (void)setBalance:(double)theBalance {
        if (theBalance != _balance) {
            [self willChangeValueForKey:@"balance"];
            _balance = theBalance;
            [self didChangeValueForKey:@"balance"];
        }
    }
    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
        BOOL automatic = NO;
        if ([theKey isEqualToString:@"balance"]) {
            automatic = NO;
        }
        else {
            automatic = [super automaticallyNotifiesObserversForKey:theKey];
        }
        return automatic;
    }
    

    현재 대상의 자동 호출 과정, 즉 상기 두 가지 방법으로 시작된 KVO 호출을 제어하려면 automaticallyNotifiesObserversForKey: 방법을 다시 쓸 수 있습니다.방법이 YES로 돌아가면 호출이 가능하고 NO로 돌아가면 호출이 불가능합니다.

    KVO 구현 원리

    KVOisa-swizzling기술을 통해 이루어진 것이다(이 말은 전체 KVO이 실현한 중점이다).실행할 때 원 클래스에 따라 중간 클래스를 만듭니다. 이 중간 클래스는 원 클래스의 하위 클래스이고 현재 대상의 isa을 동적 수정하여 중간 클래스를 가리킵니다.또한 class 방법을 다시 써서 원류의 Class으로 되돌려준다.따라서 애플은 개발에서 isa 지침에 의존하지 말고 class 실례적인 방법을 통해 대상 유형을 얻자고 제안했다.
    즉, ObjectA 유형의 객체에 관찰이 추가되면 NSKVONotifyingObjectA 클래스를 가리키고 대상의 isa 바늘을 새로운 클래스로 가리킨다. 즉, 이 대상의 유형이 바뀌었다는 것이다.이 클래스는 ObjectA에 비해 다음과 같은 몇 가지 방법을 다시 쓴다.
  • 1.다시 쓰기setter.KVO의 원리는 setter 방법을 수정하는 것이기 때문에 KVO를 사용하려면 setter를 호출해야 합니다.속성 대상에 직접 접근하면 효과가 없습니다.
  • 2.다시 쓰기class.이사 지향을 수정한 후,class의 반환 값은 변하지 않지만,isa의 값은 변경됩니다.
  • 3.dealloc를 다시 씁니다.시스템에서 자원을 방출하기 위해 dealloc 방법을 다시 씁니다.
  • 4.다시 쓰기isKVOA. 이 개인 방법은 이 클래스가 KVO 메커니즘이 주장하는 클래스임을 표시하는 데 쓰인다.

  • 코드로 KVC/KVO의 실현 원리를 탐구하는 이 글을 참고하여 코드를 한 걸음 한 걸음 분석함으로써 단점 캡처를 보면 위에서 다시 쓴 방법을 잘 증명할 수 있다.

    좋은 웹페이지 즐겨찾기