THIS IS ELLIE

KVO (Key Value Observing) 본문

개발/Objective-C

KVO (Key Value Observing)

Ellie Kim 2020. 2. 24. 16:58

현재 진행하는 프로젝트에서

API 리퀘스트를 날려 받아온 데이터를 디코딩하고 넣어줍니다.

프로퍼티가 새로운 데이터가 들어옴을 감지하면 tableView를 리로드 시켜줍니다.

 

사실 스위프트에서는 그냥 프로퍼티 옵져버를 사용하는데요.

오브젝티브씨에서는 KVO key value observing이라는 친구가 있습니다.

KVO는 오브젝트 값의 변화를 통지, 감시하기 위한 구조입니다.

특정 인스턴스의 특정 프로퍼티가 변화했을 때를 파악해 그에 맞는 처리를 할 수 있습니다.

 

위에서 오브젝트 값의 변화를 통지, 감시한다라고 했죠.

KVO를 사용하려면 먼저 NSObject를 상속받아야 합니다. 

즉 클래스여야 합니다.

 

KVO를 그림으로 나타내자면 아래와 같은 흐름입니다.

resource : https://www.appcoda.com/understanding-key-value-observing-coding/

이제 실제로 사용해봅시다.

 

KVO로그를 찍기 위해 A, B 클래스를 작성하고 구현했습니다.

AClass의 intValue를 두고 BClass에서 이 프로퍼티의 변화함을 감지하는 작업을 해보겠습니다.

// A Class 생성 및 구현
@interface AClass : NSObject {
    NSInteger intValue;
}
-(void) setIntValue:(NSInteger)i;
@end

@implementation AClass
-(void) setIntValue:(NSInteger)i {
    intValue = i;
}
@end

// B Class 생성 및 구현

@interface BClass : NSObject
-(void) observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context;
@end

@implementation BClass
-(void) observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context {
    NSLog(@"값 변경: %@", [change description]);
}
@end

먼저 옵저버를 등록하기 위해서 addObserver:forKeyPath:options:context를 사용합니다.

이를 통해 값이 변경됨을 확인할 수 있습니다.

값이 변경되면 등록된 인스턴스의 observeValueForKeyPath:ofObject:change:context가 호출됩니다. 

 

 

이제 메인함수에서 각 클래스 인스턴스를 만들어주고 옵저버를 등록해줍니다.

(메인함수가 아니어도 필요한 곳에서 등록해주면 됩니다.)

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        AClass *instanceA = [[AClass alloc] init];
        BClass *instanceB = [[BClass alloc] init];
        
        [instanceA setIntValue:1];
        
        NSKeyValueObservingOptions option = (NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld);
        [instanceA addObserver:instanceB
                    forKeyPath:@"intValue"
                       options:option
                       context:nil];
        
        [instanceA setIntValue:2];
        
        [instanceA removeObserver:instanceB
                            forKeyPath:@"intValue"];
    }
    return 0;
}

 

 

 

옵저버를 등록할 때 keyPath를 주의해서 작성해줍니다.

이는 내가 감지할 프로퍼티나 메서드등을 동일하게 문자열로 표기해줘야 합니다.

만약 intValue 프로퍼티를 감지하려 하는데 keyPath로 stringValue로 작성하면 당연히 변화가 감지 안 되겠죠.

 

또한 더 이상 사용하지 않거나 인스턴스가 소멸한다면 옵저버를 해지해줘야 합니다. 

이럴 때는 removeObserver:forKeyPath를 사용할 수 있습니다.

 

반응형

'개발 > Objective-C' 카테고리의 다른 글

오브젝티브씨 isKindOfClass  (0) 2020.04.06
Objective-C 프로퍼티 속성  (0) 2020.03.26
Objective-C id 타입  (0) 2020.02.20
조건문와 반복문  (0) 2020.02.12
오브젝티브씨 문자열 포맷팅  (0) 2020.01.22