KVC/KVO

70882 단어
KVC
  • 전체 이름: 키 값 코드
  • 부가
  •        
          
          
          
    1
    2
    3
    4
           
          
          
          
    - ( void)setValue:( id)value forKey:( NSString *)key;
    - ( void)setValue:( id)value forKeyPath:( NSString *)keyPath;
    - ( void)setValuesForKeysWithDictionary:( NSDictionary *)keyedValues;
    • 取值
           
          
          
          
    1
    2
    3
    4
           
          
          
          
    //
    - ( id)valueForKey:( NSString *)key;
    - ( id)valueForKeyPath:( NSString *)keyPath;
    - ( NSDictionary *)dictionaryWithValuesForKeys:( NSArray *)keys;
  • KVC의 기본 구현
  •        
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
           
          
          
          
    + ( instancetype)flagWithDict:( NSDictionary *)dict
    {
    Flag *flag = [[ self alloc] init];
    // KVC
    // KVC , key
    [flag setValuesForKeysWithDictionary:dict];
    // 1. key ,name,icon
    // enumerateKeysAndObjectsUsingBlock: keys valus
    // [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    // NSLog(@"%@ %@",key,obj);
    //
    // // KVC ,,
    // // key:
    // // Value:
    // [flag setValue:obj forKey:key];
    //
    // }];
    // 2.[flag setValue:dict[@"name"] forKey:@"name"];
    // [flag setName:dict[@"name"]] _name = dict[@"name"
    // flag.icon = [UIImage imageNamed:dict[@"icon"]];
    return flag;
    }
    // [flag setValue:obj forKey:key];
    // [flag setValue:dict[@"icon"] forKey:@"icon"];
    // setValue:forKey: :
    //
    // 1. setIcon , set , [self setIcon:dict[@"icon"]]
    // 2. icon , , icon = dict[@"icon"]
    // 3. _icon , , _icon = dict[@"icon"]
    // 4. ,[ setValue:forUndefinedKey:]
    - ( void)setIcon:( NSString *)icon
    {
    _icon = [ UIImage imageNamed:icon];
    NSLog( @"%@", [icon class]);
    }

    KVO

    • 全称:Key Value Observing(键值监听)
    • 作用:监听模型的属性值改变
    • 步骤
      • 添加监听器
    • KVO是一个观察者模式。观察一个对象的属性,注册一个指定的路径,若这个对象的的属性修改,则KVO会自动通知观察者。
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
           
          
          
          
    // b a name
    /**
    * p ( )
    *
    * @param Observer: ( )
    * @param KeyPath: (
    */
    [a addObserver:b forKeyPath: @"name" options: NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context: @"test"];
    /** */
    [a removeObserver:b forKeyPath: @"name"];
    -            
    
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
           
          
          
          
    /**
    * KVO ,
    *
    * @param keyPath
    * @param object
    * @param change
    * @param context addObserver context
    */
    -( void)observeValueForKeyPath:( NSString *)keyPath ofObject:( id)object change:( NSDictionary *)change context:( void *)context
    {
    NSLog( @"%@ %@ %@ %@", object, keyPath, change, context);
    }
  • KVO의 관찰자는 두 가지 모델이다.하나는 자동 알림이고, 하나는 수동 알림이다.
  • 자동 감청 대상의 속성을 자동으로 통지하고 이 속성의 전후 속성 변화의 값이 같든 그렇지 않든 관찰자에게 통지한다.
  • 수동 알림 다시 쓰기willChangeValueForKey:와didChangeValueForKey:방법 알림 관찰자.
  • 보통 자동 알림으로 편리하고 빠르다.아래의 두 가지 작법은 모두 예를 들어 설명할 것이다.

  • 자동 알림, 주로 감청 리셋의 분석 장면을 본다. 사람의 나이 변화를 모의하고 알림을 받는 횟수
  • 를 본다.
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
           
          
          
          
    - ( void)viewDidLoad {
    [ super viewDidLoad];
    self.person = [[Person alloc]init];
    self.person.age = 15;
    /**
    *
    */
    [ self.person addObserver: self forKeyPath: @"age" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil];
    /**
    * 20
    */
    self.person.age = 20;
    /**
    * 20
    */
    self.person.age = 20;
    /**
    * ,
    */
    }
    /**
    *
    */
    -( void)observeValueForKeyPath:( NSString *)keyPath ofObject:( id)object change:( NSDictionary< NSString *, id> *)change context:( void *)context{
    NSLog( @"n change = %@ n keyPath =%@ object =%@ context=%@",change ,keyPath,object,context);
    /** ============================ ===================================
    *
    change = {
    kind = 1;
    new = 20; ---------> 20 ,observeValueForKeyPath
    old = 15; ---------> 15 , 15。
    }
    keyPath =age object = context=(null)
    change = {
    kind = 1;
    new = 20; ---------> 20 20,observeValueForKeyPath
    old = 20; ---------> 20
    }
    keyPath =age object = context=(null)
    */
    /**
    * , , , ,observeValueForKeyPath , 。
    */
    }
    -( void)dealloc{
    /**
    *
    */
    [ self.person removeObserver: self forKeyPath: @"age"];
    • 手动通知
      场景:模拟人年龄的变化,看接受通知的次数
      需要在Person类里面重写方法,具体看实现代码
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
           
          
          
          
    - ( void)viewDidLoad {
    [ super viewDidLoad];
    self.person = [[Person alloc]init];
    self.person.age = 15;
    /**
    *
    */
    [ self.person addObserver: self forKeyPath: @"age" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context: nil];
    /**
    * 20
    */
    self.person.age = 20;
    /**
    * 20
    */
    self.person.age = 20;
    /**
    * ,
    */
    }
    /**
    *
    */
    -( void)observeValueForKeyPath:( NSString *)keyPath ofObject:( id)object change:( NSDictionary< NSString *, id> *)change context:( void *)context{
    NSLog( @"n change = %@ n keyPath =%@ object =%@ context=%@",change ,keyPath,object,context);
    /** ============================ ===================================
    *
    change = {
    kind = 1;
    new = 20; ---------> 20 ,observeValueForKeyPath
    old = 15; ---------> 15 , 15。
    }
    keyPath =age object = context=(null)
    */
    /**
    * , 。 Person automaticallyNotifiesObserversForKey 。 age setter
    * , ,observeValueForKeyPath , 。
    */
    }
    -( void)dealloc{
    /**
    *
    */
    [ self.person removeObserver: self forKeyPath: @"age"];
    • Person类的实现
           
          
          
          
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    //
    // Person.m
    // KVO
    //
    // Created by XXXXXX on 15/11/9.
    // Copyright © 2015 . All rights reserved.
    //
    @implementation
    -( void)setAge:( float)age{
    /**
    * ,
    */
    if (_age!= age) {
    [ self willChangeValueForKey: @"age"];
    _age = age;
    [ self didChangeValueForKey: @"age"];
    }
    }
    /**
    * key
    *
    * @param theKey key
    *
    * @return
    */
    + ( BOOL)automaticallyNotifiesObserversForKey:( NSString *)theKey {
    BOOL automatic = NO;
    if ([theKey isEqualToString: @"age"])
    {
    automatic = NO;
    }
    else
    {
    automatic=[ super automaticallyNotifiesObserversForKey:theKey];
    }
    return automatic;
    }
    @end
  • 자동 알림과 수동 알림을 관찰했는데 각각 장점이 있다.

  • 주의: 수동 알림은 새 값과 낡은 값의 앞뒤가 달라야만 알림을 다시 쓸 수 있습니다.자동 알림은 신구치가 같든 그렇지 않든 관찰자에게 알려준다.
    전문 코너 KVC/KVO

    좋은 웹페이지 즐겨찾기