iOS 개발 - KVO

7673 단어

도입부


KVO: Key-Value-Observer, 키 값 관측 모드로, 특정 객체의 특정 속성 값이 변경될 때 객체의 관찰자(다른 객체)에게 즉시 알릴 수 있는 메커니즘입니다.

관찰자의 등록 및 제거


KVO의 대략적인 절차는 감청할 속성에 속하는 클래스에 관찰자를 추가하는 것이다.속성 변경에 대한 알림을 받고 처리하기;처리가 끝난 후 관찰자를 접촉하는 3대 절차.코끼리를 냉장고에 넣으려면 모두 몇 걸음이 걸리는 것처럼 절차가 간단하다.그 중에서 일대일은 비집합류의 속성에 대한 감청을 대표하고 일대일은 집합류의 속성에 대한 감청을 대표한다.

등록!


등록 방법:
[person addObserver:observer
             forKeyPath:@"age"
                options:NSKeyValueObservingOptionNew
                context:NULL];

각 매개 변수의 의미는 매우 명확하다.각각 피관찰류의 실례 대상, 관찰자류의 실례 대상, 피관찰의 속성 명칭, 관찰 옵션, 추가 매개 변수 순이다.

등록 옵션


등록 옵션은 다음과 같은 네 가지로 구성됩니다.
  • NSKeyValueObservingOptionNew: 관찰자의 속성이 변할 때의 새로운 값을 알립니다.
  • NSKeyValueObservingOptionOld: 관찰자의 속성이 변할 때 이전의 옛 값을 알린다.
  • NSKeyValueObservingOptionInitial: 관찰자 방법addObserver:observer을 등록하고 돌아오지 않을 때 알림을 보내기 시작합니다. 피관찰자의 초기화(initial value)는 관찰자에게 새로운 변화의 값이기 때문입니다.
  • NSKeyValueObservingOptionPrior: 두 가지 통지를 보냅니다. 즉, 속성 값이 곧 변화할 때, 즉 다음에 말하고자 하는 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조의 kindNSKeyValueChange 유형의 매거값으로 다음과 같은 네 가지 정의가 있다.
  • NSKeyValueChangeSetting: 새 값을 설정합니다. 감청되는 것은 일대일 속성 또는 일대다 속성입니다.
  • NSKeyValueChangeInsertion: 한 쌍의 여러 속성에 새로운 객체가 삽입되었습니다.
  • NSKeyValueChangeRemoval: 한 쌍의 여러 속성이 한 대상을 제거했습니다.
  • NSKeyValueChangeReplacement: 한 쌍의 여러 속성이 그 중의 어떤 대상을 교체했다.

  • 제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 방법의 이전 다음에 willChangeValueForKeydidChangeValueForKey를 자동으로 호출하여 같은 속성의 수정을 두 번 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의 속성이 있는데 이것은 대상의 nameage의 조합을 되돌려준다.
    - (NSString *)personInfo
    {
        return [NSString stringWithFormat:@"person's name:%@ age:%d", self.name, self.age];
    }
    

    만약 우리가 personInfo에 대해 감청을 한다면 nameage의 변화도 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 상세 설명

    좋은 웹페이지 즐겨찾기