KVO의 진일보한 이해

6126 단어
이것은 간단하면서도 풍부한 주말입니다.

1. KVO 개요 및 간단한 사용


KVO는 일종의 감청이다. 어떻게 감청을 할 수 있을까?먼저 다음과 같은 간단한 Class를 만듭니다.
#import 

@interface KVOObject : NSObject

//   
@property (nonatomic, copy) NSString* name;

@end



#import "KVOObject.h"

@implementation KVOObject

@end

간단합니다. 클라스 하나에 name 속성을 정의했을 뿐입니다.
간단한 테스트는 다음과 같습니다.
//      KVO   
KVOObject* kvObj = [[KVOObject alloc] init];
kvObj.name = @"HG";

//    KVO   
[kvObj addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];

kvObj.name = @"CoderHG";

//    KVO   ,   iOS 10          crash,        
[kvObj removeObserver:self forKeyPath:@"name"];

구체적인 스니퍼 방법 코드는 다음과 같습니다.
// KVO        
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"%@, %@, %@", keyPath, object, change);
}

이상은 간단하면서도 완전한 KVO의 사용 장면인데 구체적인 원리는 무엇입니까?

2. KVO의 원리에 대한 초보적인 인식


한 대상이 KVO 감청을 추가하면 본질적으로 시스템이 이 대상의 이사 지침을 동적으로 바꾼 것으로 알려져 있다.이사에 대해 잘 모르면 이 OC 테마를 볼 수 있습니다.이사가 어떤 변동이 있는지 알고 싶으면 다음과 같은 방법을 먼저 실현한다.
//       cls       
- (NSString*)printMethodNamesOfClass:(Class)cls {
    unsigned int count;
    //       
    Method *methodList = class_copyMethodList(cls, &count);
    
    //      
    NSMutableString *methodNames = [NSMutableString string];
    
    //        
    for (int i = 0; i < count; i++) {
        //     
        Method method = methodList[i];
        //      
        NSString *methodName = NSStringFromSelector(method_getName(method));
        //      
        [methodNames appendString:methodName];
        [methodNames appendString:@", "];
    }
    
    //   
    free(methodList);
    
    //          
    return [NSString stringWithFormat:@"  : %@ 
: %@", NSStringFromClass(cls), methodNames]; }

그런 다음 위의 시험을 다음과 같이 수정합니다.
//     
- (void)convention {
    //      KVO   
    KVOObject* kvObj = [[KVOObject alloc] init];
    kvObj.name = @"HG";
    
    Class cls = object_getClass(kvObj);
    NSString* isaInfo = [self printMethodNamesOfClass:cls];
    
    NSLog(@"

KVO :
%@", isaInfo); // KVO [kvObj addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; kvObj.name = @"CoderHG"; cls = object_getClass(kvObj); isaInfo = [self printMethodNamesOfClass:cls]; NSLog(@"

KVO :
%@", isaInfo); // KVO , iOS 10 crash, [kvObj removeObserver:self forKeyPath:@"name"]; }

로그는 다음과 같이 인쇄됩니다.
   KVO   :
  : KVOObject 
    : .cxx_destruct, name, setName:

   KVO   :
  : NSKVONotifying_KVOObject 
    : setName:, class, dealloc, _isKVOA

KVO 스니핑을 추가한 후 isa 포인터의 값이 변경되었음을 나타냅니다. 이 값은 다음과 같습니다.
4
  • 1、이전 KVOObject를 NSKVONotifying 로 교체KVOObject

  • 4
  • 2、NSKVONotifyingKVOObject에서 setName:,class 및 dealloc 메서드를 재작성하고isKVOA 방법.

  • 3. KVO와 KVC의 인연


    KVC에 관해서는 이 글의 KVC의 원리 개술을 강력히 권장하며, 이어서 이 글의 기초 위에서 소개할 것이다.만약 보지 않는다면, 아마도 내가 말한 비상규격 KVC 호출이 무슨 뜻인지 이해하기 어려울 것이다.비록 나는 이곳에서 단지 그 정도의 내용을 썼을 뿐이다.먼저 다음과 같은 Class를 만듭니다.
    #import 
    
    @interface KVO8KVCObject : NSObject
    
    @end
    
    
    #import "KVO8KVCObject.h"
    
    @interface KVO8KVCObject ()
    {
        //      
        NSString* isGoddess;
    }
    
    @end
    
    @implementation KVO8KVCObject
    
    @end
    

    그럼 이제 우리는 어떤 문제를 표현하고 싶습니까?
    KVC가 KVO 감청을 촉발할 수 있습니까?
    위의 KVO8KVCObject 정의를 보고 KVC의 비상규 호출을 사용할 것입니다. 구체적인 코드는 다음과 같습니다.
    // KVO   KVC           
    - (void)kvo8kvc {
       //      KVO8KVC   
       KVO8KVCObject* kvO_CObj = [[KVO8KVCObject alloc] init];
       
       //    KVC   
       [kvO_CObj setValue:@"KJ" forKey:@"goddess"];
       
       Class cls = object_getClass(kvO_CObj);
       NSString* isaInfo = [self printMethodNamesOfClass:cls];
       
       NSLog(@"

    KVO :
    %@", isaInfo); // KVO [kvO_CObj addObserver:self forKeyPath:@"goddess" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; // KVC [kvO_CObj setValue:@"JK" forKey:@"goddess"]; cls = object_getClass(kvO_CObj); isaInfo = [self printMethodNamesOfClass:cls]; NSLog(@"

    KVO :
    %@", isaInfo); // KVO , iOS 10 crash, [kvO_CObj removeObserver:self forKeyPath:@"goddess"]; }

    다음과 같은 Log 인쇄를 살펴보십시오.
       KVO   :
      : KVO8KVCObject 
        : .cxx_destruct
    

    goddess, , {
        kind = 1;
        new = JK;
        old = KJ;
    }
    

       KVO   :
      : NSKVONotifying_KVO8KVCObject 
        : class, dealloc, _isKVOA
    

    KVC는 KVO 감청을 촉발할 수 있다는 결론을 얻을 수 있다.
    여기를 보고 이전의 결론을 뒤집었다. KVO의 정상적인 촉발 입구는 setter 방법이다. 사실은 그렇지 않다. 위의 이 실험과 같이 NSKVONotifyingKVO8KVCObject와 KVO8KVCObject에는 대응하는setter 방법이 전혀 없습니다.

    면접 문제


    KVO는 컬렉션 클래스를 어떻게 모니터링합니까?
    이 면접 문제는 주로 집합 클래스의 요소 변동에 대한 감청이다. 예를 들어 하나의 그룹이 어떻게 추가, 삽입, 삭제를 감청하는지를 말한다.일반적인 KVO 방식으로는 감지할 수 없지만 시스템은 이미 우리를 위해 전문적인 API를 준비했다.구체적인 설명은 InterviewKVOcontroller의 구체적인 실현을 참고하십시오.
    /** KVO          ?
     1.        Class (KVObject),      Class           
     2.        mutableArrayValueForKey:       .     .
     */
    

    본 편의 소개는 여기서 곧 일단락된다.책을 쓸 때 데모 # OC2 Nature를 시험해 봤는데 참고할 수 있습니다.자세한 내용은 KVO 카탈로그를 참조하십시오.동시에 본 주제의 다른 문장 OC 작은 주제를 보는 것을 잊지 마라
    이전에도 KVO에 대해 썼는데 그때는 이해가 깊지 않았지만 그 안에 새로운 것이 있다.관심 있으면 가보세요.
    4
  • 1. 간단한 KVO 실현 방식: KVO의 기능을 간접적으로 실현한다

  • 4
  • 2, KVO와Category:A.@property 문법이 서로 다른 장면에서의 의미와 주의사항.B. Category에서 KVO 감청이 이루어졌습니다
  • 좋은 웹페이지 즐겨찾기