iOS 개발 - KVO
도입부
KVO: Key-Value-Observer, 키 값 관측 모드로, 특정 객체의 특정 속성 값이 변경될 때 객체의 관찰자(다른 객체)에게 즉시 알릴 수 있는 메커니즘입니다.
관찰자의 등록 및 제거
KVO의 대략적인 절차는 감청할 속성에 속하는 클래스에 관찰자를 추가하는 것이다.속성 변경에 대한 알림을 받고 처리하기;처리가 끝난 후 관찰자를 접촉하는 3대 절차.코끼리를 냉장고에 넣으려면 모두 몇 걸음이 걸리는 것처럼 절차가 간단하다.그 중에서 일대일은 비집합류의 속성에 대한 감청을 대표하고 일대일은 집합류의 속성에 대한 감청을 대표한다.
등록!
등록 방법:
[person addObserver:observer
forKeyPath:@"age"
options:NSKeyValueObservingOptionNew
context:NULL];
각 매개 변수의 의미는 매우 명확하다.각각 피관찰류의 실례 대상, 관찰자류의 실례 대상, 피관찰의 속성 명칭, 관찰 옵션, 추가 매개 변수 순이다.
등록 옵션
등록 옵션은 다음과 같은 네 가지로 구성됩니다.
addObserver:observer
을 등록하고 돌아오지 않을 때 알림을 보내기 시작합니다. 피관찰자의 초기화(initial value)는 관찰자에게 새로운 변화의 값이기 때문입니다.willChangeValueForKey
의 촉발 시간은 상대적으로 관찰자에게 미리 통지를 보내고 속성 값이 바뀌면 상기 세 가지 옵션과 같이 통지를 보냅니다.알림 처리
관찰자는 통지를 받은 후 특정한 방법으로 처리해야 한다. 예시 코드:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(@"%@", change);
if ([keyPath isEqualToString:@"name"])
{
//
NSLog(@"%@ !%@", object, change);
}
}
이 방법은 반드시 관찰자의 분류에서 다시 써야 한다.
알림 메시지
알림 처리 방법
change:(NSDictionary *)change
은 사전 유형의 대상으로 이번 변화에 대한 정보를 포함한다. 예를 들어 NSKeyValueObservingOptionNew
옵션에서 1대1 속성이 변할 때 받는 변화 정보는 다음과 같다.{
kind = 1;
new = hexintao;
}
제1조의
kind
는 NSKeyValueChange
유형의 매거값으로 다음과 같은 네 가지 정의가 있다.제2조는
NSKeyValueObservingOptions
관찰 옵션, 일대일 또는 일대다의 속성에 따라 다르다.대체로 설정된 새 값, 변화하기 전의 옛 값, 또는 여러 속성의 추가, 제거, 교체 대상과 번호(index) 등을 나타낸다.구체적인 정보는 command
+observeValueForKeyPath
로 통지 처리 방법의 공식 주석을 볼 수 있으며 매우 상세하게 쓰여 있다.제거
등록 정보 값이 변경된 알림을 처리한 후 등록된 관찰자를 수동으로 해제해야 합니다. 해제하는 방법은 다음과 같습니다.
- (void)removeObserver:(NSObject *)anObserver
forKeyPath:(NSString *)keyPath
- (void)removeObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
context:(void *)context
수신되지 않은 속성(keyPath)에 대해 해제 작업을 실행하면 이상이 발생합니다.마찬가지로 이미 등록된 감청 속성에 대해 해제 작업을 실행하지 않으면 이상이 발생합니다.
자동 및 수동 알림
위의 절차에 따라 실행하면 기본적으로 자동 알림을 사용합니다. 즉, 속성 값에 다시 값을 부여하면 (새 값과 옛 값이 같든 상관없이) 관찰자는 알림을 받을 수 있습니다.실제 응용에서 우리는 자신의 수요에 따라 속성 값이 우리의 조건을 만족시킨 후에야 관찰자에게 알림을 보내려고 할 수 있다. 이때 우리는 수동 모드를 통해 알림을 보내는 조건과 시간을 수정하여 목적을 달성해야 한다.
자동 알림 1
위에서 설명한 대로 공지를 보낼 시기와 조건은 수정할 수 없습니다.
//
[person setValue:@"hexintao" forKey:@"name"];
// ,
[person setValue:@"hexintao" forKey:@"name"];
[person setValue:@"hexintao" forKey:@"name"];
물론 실제 응용에서 같은 값을 연속으로 부여하는 경우는 흔치 않고 추천하지 않습니다. 우리는 단지 이를 통해 자동 알림 모드의 상황을 설명하기 위해서입니다.
수동 알림
우선 자동 알림을 닫고 피관찰자의 클래스에서 클래스를 다시 쓰는 방법을 닫아야 한다. (2017.01.04 수정: 이 클래스를 다시 쓰지 않으면 시스템은 속성setter 방법의 이전 다음에
willChangeValueForKey
과didChangeValueForKey
를 자동으로 호출하여 같은 속성의 수정을 두 번 KVO 감청 방법으로 조정한다.)+ (BOOL)automaticallyNotifiesObserversOf
{
return NO;
}
또는
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
BOOL automatic = YES;
if ([key isEqualToString:@"name"])
{
automatic = NO;
}
else
{
automatic = [super automaticallyNotifiesObserversForKey:key];
}
}
다음 방법은 비교적 복잡하고 속성 명칭(
key
을 잘못 맞출 위험이 있기 때문에 첫 번째 방법을 추천합니다.다음에 알림을 보내야 하는 곳에서 수동으로 두 가지 방법을 호출해야 한다. 이 예에서 우리는 속성 값setter
방법을 얻는다.- (void)setName:(NSString *)name
{
if (name != _name)
{
// , KVO
// , KVO
[self willChangeValueForKey:@"name"];
_name = name;
[self didChangeValueForKey:@"name"];
}
}
상술한 두 가지 방법은 반드시 쌍으로 호출해야만 성공적으로 통지를 보낼 수 있다.아까 그 예:
//
[person setValue:@"hexintao" forKey:@"name"];
// ,
[person setValue:@"hexintao" forKey:@"name"];
[person setValue:@"hexintao" forKey:@"name"];
키 의존 등록
때때로 우리가 감청하는 어떤 속성 값은 다른 여러 속성에 의존할 수 있다. 다른 속성이 바뀌면 우리가 감청하는 속성에 변화가 생길 수 있다. 이런 것을 의존키라고 한다.예를 들어
Person
클래스에는 personInfo
의 속성이 있는데 이것은 대상의 name
과 age
의 조합을 되돌려준다.- (NSString *)personInfo
{
return [NSString stringWithFormat:@"person's name:%@ age:%d", self.name, self.age];
}
만약 우리가
personInfo
에 대해 감청을 한다면 name
와age
의 변화도 personInfo
에 변화를 초래할 수 있으므로 의존키를 설정해야 한다.+ (NSSet *)keyPathsForValuesAffectingPersonInfo
{
return [NSSet setWithObjects:@"name", @"age", nil];
}
그리고
personInfo
에 대해 등록 감청을 한 다음에 name
또는 age
의 값을 수정할 때 관찰자는 이런 통지를 받는다.CollectionViewTest[742:17933] {
kind = 1;
new = "person's name:hexintao age:0";
}
즉, 관련 속성 중 어느 하나에 변화가 발생하면 우리가 감청하는 이 속성은 그 값에 변화가 생겼음을 알리는 통지를 받는다.
집합 속성의 감청
집합 속성의 전체입니까 아니면 부분입니까?
일대일 속성의 감청은 상대적으로 간단하다. 값에 변화가 생기면 우리는 통지를 받고 처리하면 된다.한 쌍의 다중 집합류의 속성에 대해 말하자면 전체 집합이 발생하는 변화를 감청하는 것이냐 아니면 그 중의 원소의 변화를 감청하는 것이냐?이 두 가지 행위는 모두 KVO를 통해 감청할 수 있지만 일상적으로 사용하면 후자를 감청하는 경향이 강하다.집합 속성에 대해 정상적으로 대상을 추가하거나 삭제하는 작업은 KVO를 촉발할 수 없다. 예를 들어
[person.personFriends addObject:@"2in"]
관찰자는 변화 알림을 받지 않지만 집합 속성 전체의 변화, 예를 들어person.personFriends = [[NSMutableArray alloc]init]
에 대해 관찰자는 정상적으로 알림을 받을 수 있다.그러나 우리는 특정한 방법을 통해 집합 속성 중의 대상의 변화를 감청하는 것을 중점적으로 토론한다.크게 두 가지 방법으로 나뉜다.수동 모니터
집합 속성의 수동 감청: 감청된 클래스에서 집합 요소를 수정하는 방법을 다시 쓰고, 이 방법을 사용해서 속성을 수정하면 KVO 감청을 촉발할 수 있습니다.우리는 필요에 따라 다음과 같은 것을 실현할 수 있다.
//
- (void)insertObject:(id)object inAtIndex:(NSUInteger)index
//
-(void)removeObjectFromAtIndex:(NSUInteger)index
구체적인 조작 요소의 방법은 공식 매뉴얼을 볼 수 있다. KVC의 공식 지도 후에 우리는 다시 쓴 방법을 호출하여 집합 속성을 수정할 때 KVO를 터치할 수 있다.
자동 감청
자동 감청은 대체로
mutableArrayValueForKey
방법을 통해 가변 대상의 에이전트를 얻어 이를 수정하면 자동으로 KVO를 촉발할 수 있다.valueForKey
가 되돌아오는 것은 변할 수 없는 대상이다.사용 예:[[person mutableArrayValueForKey:@"personFriends"] addObject:@"3in"];
// , addObject KVO 。
NSMutableArray *friends = [person mutableArrayValueForKey:@"personFriends"];
// KVO
[person.personFriends addObject:@"4in"];
// KVO, friends person.personFriends , ,
// friends person.personFriends , !
[friends insertObject:@"5in" atIndex:0]; // KVO
[friends removeObjectAtIndex:0]; // KVO
참고 자료
Apple KVO 공식 브로셔 NSHipster KVO 가변 대상 KVO에서의 감청 KVO 상세 설명
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.