KVO 원리 분석
개술
KVO
은 전칭 KeyValueObserving
으로 키값 관찰로 번역된 애플이 제공한 이벤트 알림 메커니즘이다.대상이 다른 대상의 특정한 속성 변화를 감청하고 변경할 때 이벤트를 받을 수 있도록 합니다.KVO
의 실현 메커니즘으로 인해 속성에 작용이 발생한다. 일반적으로 NSObject
에서 계승된 대상은 모두 KVO
을 기본적으로 지원한다.KVO
과 NSNotificationCenter
은 모두 iOS에서 관찰자 모델의 일종의 실현이다.차이점은 피관찰자와 관찰자 간의 관계에 비해 KVO
은 일대일이지 일대일이 아니라는 점이다.KVO
은 피감청 대상에 침입성이 없고 내부 코드를 수정하지 않아도 감청을 실현할 수 있다.KVO
은 단일 속성의 변화도 감청할 수 있고 집합 대상의 변화도 감청할 수 있다.KVC
의 mutableArrayValueForKey:
등 방법을 통해 대리 대상을 얻고 대리 대상의 내부 대상이 바뀔 때 KVO
의 감청 방법을 되돌린다.집합 대상은 NSArray
과 NSSet
이다.기본 사용
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
을 초래할 수 있다.등록 방법
NSKeyValueObservingOptionNew
과 NSKeyValueObservingOptionOld
이 들어오면 새 값과 낡은 값만 받는다고 표시되며, 기본값은 새 값만 받는다.관찰자 등록 후 즉시 리콜을 한 번 받으려면 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 간에 통신합니다.주의점
KVO
의 addObserver
과 removeObserver
은 짝을 지어야 한다. remove
을 반복하면 NSRangeException
유형의 Crash
을 초래하고 remove
을 잊어버리면 관찰자가 석방된 후에 다시 KVO를 받을 때 Crash
이다.addObserver
, dealloc
에서 removeObserver
으로 add
과 remove
이 짝을 지어 나타나는 이상적인 사용 방식이다.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 구현 원리
KVO
은 isa-swizzling
기술을 통해 이루어진 것이다(이 말은 전체 KVO
이 실현한 중점이다).실행할 때 원 클래스에 따라 중간 클래스를 만듭니다. 이 중간 클래스는 원 클래스의 하위 클래스이고 현재 대상의 isa
을 동적 수정하여 중간 클래스를 가리킵니다.또한 class
방법을 다시 써서 원류의 Class
으로 되돌려준다.따라서 애플은 개발에서 isa
지침에 의존하지 말고 class
실례적인 방법을 통해 대상 유형을 얻자고 제안했다.즉, ObjectA 유형의 객체에 관찰이 추가되면 NSKVONotifyingObjectA 클래스를 가리키고 대상의 isa 바늘을 새로운 클래스로 가리킨다. 즉, 이 대상의 유형이 바뀌었다는 것이다.이 클래스는 ObjectA에 비해 다음과 같은 몇 가지 방법을 다시 쓴다.
코드로 KVC/KVO의 실현 원리를 탐구하는 이 글을 참고하여 코드를 한 걸음 한 걸음 분석함으로써 단점 캡처를 보면 위에서 다시 쓴 방법을 잘 증명할 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.