iOS 개발 KVC

11289 단어 총결산

iOS 개발 KVC


KVC 소개:
KVC(key-value codeing)는 애플이 제공하는 실행 시 기반 인코딩 기술이다.이것은 개발자가 키 값을 통해 대상에 대응하는 속성에 직접 접근할 수 있도록 하고 set, get 방법을 명확하게 호출할 필요가 없기 때문에 kvc는 실행할 때 동적으로 대상의 속성을 수정할 수 있다. 이것도 그의 강점이다.대상이 속성을 실현하는 set, get 방법이 없다면, 그 속성 값을 kvc로 직접 저장할 수 있습니다. 이 변수가 클래스 인터페이스에서 정의되었든, 클래스에서 정의되었든, 어떤 접근 수식자를 사용했든, 이름으로만 존재하는 변수든, KVC는 이 구성원 변수에 값을 부여할 수 있습니다.만약에 속성이 set, get 방법을 실현한다면 가능한 set, get 방법을 통해 값을 저장해야 코드의 봉인성을 파괴하지 않고 안전하고 효율적이다.KVC의 정의는 모두 NSObject의 확장에서 이루어진 것이다. (NSKeyValueCodeing 클래스)그래서 NSObject의 대상을 계승해야만 KVC를 사용할 수 있고 일부 순수한 swift류의 구조체는 KVC를 사용할 수 없다.
KVC에서 주로 사용하는 몇 가지 방법은 다음과 같습니다.
  • - (nullable id)valueForKey:(NSString *)key;
  • //Key를 통해 값 가져오기
  • - (void)setValue:(nullable id)value forKey:(NSString *)key;
  • Key를 통해 값을 설정하면 NSMutable Dictionary에 값을 부여할 수도 있고, 사전 모형과 같은 대상의 속성에 값을 부여할 수도 있으며, 속성 유형이 대상value 값이면 nil이 될 수 있으며, 그렇지 않으면 nil이 될 수 없습니다. 왜냐하면 값 유형은 nil이 될 수 없기 때문입니다.value가 디지털 유형으로 직접 설정되지 않으면 NSNumber 대상으로 변환하고 다시 설정해야 하며,value가 구조체로 변환될 때 NSValues 대상으로 변환해야 값을 부여할 수 있습니다.
  • - (nullable id)valueForKeyPath:(NSString *)keyPath;
  • KeyPath에서 값을 얻으면 키 path 경로를 사용하여 심층 데이터에 접근할 수 있습니다.
  • - (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
  • KeyPath를 통해 값을 부여하면 KeyPath는 더욱 강해 보이고 kvc의 수치로 사용할 수 있다. 더욱 강한 것은 집합 중의 대상을 여러 가지 방법으로 처리할 수 있다. 예를 들어 최대치, 최소치, 평균치를 추출하고 다시 처리하는 것이다. 예는 다음과 같다(KVC의 집합 작업).
         NSArray *array = @[@3, @6, @7, @8, @10];
         // 
         NSNumber *sum = [array valueForKeyPath:@"@sum.self"];
         
         // 
         NSNumber *avg = [array valueForKeyPath:@"@avg.self"];
         
         // 
         NSNumber *max = [array valueForKeyPath:@"@max.self"];
         
         // 
         NSNumber *min = [array valueForKeyPath:@"@min.self"];
         
         // 
         NSNumber *sum = [array valueForKeyPath:@"@sum.floatValue"];
         NSNumber *avg = [array valueForKeyPath:@"@avg.floatValue"];
         NSNumber *max = [array valueForKeyPath:@"@max.floatValue"];
         NSNumber *min = [array valueForKeyPath:@"@min.floatValue"];
         
         //    :@distinctUnionOfObjects  @unionOfObjects
         NSArray * txArr = @[@"aa", @"bb",@"cc",@"aa", @"cc"];
         NSLog(@"txArr : %@", [txArr valueForKeyPath:@"@distinctUnionOfObjects.self"]);
         
         // : name name 
         NSArray * dicArr = @[@{@"zhang":@"wang", @"age":@12, @"gender":@"man"},
         @{@"name":@"zhang", @"age":@12, @"gender":@"woman"},
         @{@"name":@"li", @"age":@12, @"gender":@"man"}];
         NSLog(@"txArr : %@", [txArr valueForKeyPath:@"@distinctUnionOfObjects.name"]);
         
         // uitextFile placeholder 
         [searchField setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
    
    KVC의 몇 가지 중요한 방법:
  • + (BOOL)accessInstanceVariablesDirectly;
  • 기본적으로 YES로 돌아가며, 런타임 시 속성에 대한 Set 메서드를 찾지 못하면key,_iskey, key, iskey의 순서대로 구성원을 검색합니다. NO로 설정하면 KVC를 사용하지 않습니다. set을 찾지 못하면 get 방법은 이상을 던집니다.
  • - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
  • KVC는 set의 값이 올바른지, 값이 올바르지 않을 때 처리 논리를 추가할 수 있는 속성 값을 검증하는 API입니다.
  • - (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
  • 속성이 NSMutable Array인 경우 컬렉션 작업의 API를 가져올 수 있습니다.
  • - (nullable id)valueForUndefinedKey:(NSString *)key
  • 값을 가져올 때 키가 존재하지 않으면 이 메서드가 호출됩니다. 기본값은 예외를 던지는 것입니다. 예외를 처리하는 데 사용할 수 있습니다.
  • - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
  • 값을 설정할 때 키가 호출되지 않으면 이상을 던져서 이상을 처리할 수 있습니다.
  • - (void)setNilValueForKey:(NSString *)key;
  • SetValue 시면Value에 nil을 보내면 이 방법을 사용합니다.
  • - (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
  • 키 세트를 전송하여 해당 키 세트에 해당하는Value를 반환하고 사전 세트로 반환하여 Model 사전 변환에 사용할 수 있습니다.
  • \- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
  • Model에서 키에 대응하는 속성을 수정하는 데 사용되며, 사전 회전 모델에 사용됩니다.
    참고: setObject: forKey: NSMutable Dictionary 고유의 방법입니다.value는nil/null일 수 없지만 [NSNull null](객체 유형이기 때문에)일 수 있으며 반드시 객체여야 합니다.
    다음은 장면의 예입니다.
    4
  • KVC에 대한 값: 4
  • 다음 예에서 Cameras류는 두 개의 NiCon 유형의 속성이 있는데 그 중에서 nicon1은 공유된 속성이고 nicon1은 set, get 방법을 자동으로 생성하지 않는다.nicon2는 사유의 속성이다.NiCon 클래스에는 공유 속성 devName, 개인 속성 devNO가 있습니다.
    // Cameras.h 
    #import 
    #import "NiCon.h"
    NS_ASSUME_NONNULL_BEGIN
    
    @interface Cameras : NSObject
    
    @property(nonatomic,strong)NiCon * nicon1;
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    //Cameras.m
    #import "Cameras.h"
    
    @interface Cameras()
    
    @property(nonatomic,strong)NiCon * nicon2;
    @end
    @implementation Cameras
    // nicon1 set、get ;
    @synthesize nicon1;
    
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            
            
        }
        return self;
    }
    
    
    - (id)valueForUndefinedKey:(NSString *)key{
        
        NSLog(@" key: %@   ", key);
    
        return nil;
    }
    
    
    -(void)setValue:(id)value forUndefinedKey:(NSString *)key{
        
        NSLog(@" key : %@   ", key);
    }
    
    
    
    +(BOOL)accessInstanceVariablesDirectly{
        
    //    return NO;
    //        2019-03-11 16:49:44.899991+0800 test[2256:72136]  key : nicon1   
    //    2019-03-11 16:49:44.900311+0800 test[2256:72136] nicon1:  (null)
    
    
        return YES;
    //    2019-03-11 16:44:29.408502+0800 test[2112:64508] nicon1:  
    //    2019-03-11 16:44:29.408724+0800 test[2112:64508] nicon2:  
    //    2019-03-11 16:44:29.409306+0800 test[2112:64508] nicon1.devName:   X525
    //    2019-03-11 16:44:29.409462+0800 test[2112:64508] nicon2.devName:   X525
    
    }
    @end
    
    두 번째 클래스:
    //NiCon.h
    #import 
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NiCon : NSObject
    
    @property(nonatomic, copy)NSString * devName;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    //NiCon.m
    
    #import "NiCon.h"
    @interface NiCon()
    
    @property(nonatomic,assign) int devNO;
    
    @end
    @implementation NiCon
    
    -(BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError{
        
        return [inKey isEqualToString:@"devNO"];
    }
    @end
    
    그런 다음 view Controller에서 KVC를 사용하여 객체의 속성에 값을 지정합니다.
    //viewController.m
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        Cameras* cams = [[Cameras alloc]init];
        NiCon * nic1 = [[NiCon alloc]init];
        
        // 
        [cams setValue:nic1 forKey:@"nicon1"];
        NSLog(@"nicon1:  %@", cams.nicon1);
        // 2019-03-11 16:06:01.305184+0800 test[876:12560] nicon1:  
        
        // 
        [cams setValue:nic1 forKey:@"nicon2"];
        NSLog(@"nicon2:  %@", [cams valueForKey:@"nicon2"]);
        //    2019-03-11 16:09:26.472743+0800 test[999:20027] nicon2:  
    }
    
    상기 예시에서 알 수 있듯이 공유 속성이든 개인 속성이든 KVC는 모두 성공적으로 값을 부여하고 값을 얻을 수 있기 때문에 KVC는 액세스 수식자의 제한을 받지 않는다.
    다음은 Cameras의 속성 nicon1의 속성 이름을 로 변경합니다.nicon1, isNicon1, 그리고 +(BOOL)accessInstanceVariablesDirectly 반환값을 각각 YES와 NO로 설정하여 값을 부여할 수 있는지 확인합니까?
    //Cameras.h
    //@property(nonatomic,strong)NiCon * _nicon1;
    //@property(nonatomic,strong)NiCon * isNicon1;
    
    
    //NiCon.m
    // Key , , , 。
    - (id)valueForUndefinedKey:(NSString *)key{
        
        NSLog(@" key: %@   ", key);
        return nil;
    }
    
    -(void)setValue:(id)value forUndefinedKey:(NSString *)key{
        
        NSLog(@" key : %@   ", key);
    }
    
    
    +(BOOL)accessInstanceVariablesDirectly{
        
    //    return NO;
    
        return YES;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        Cameras* cams = [[Cameras alloc]init];
        NiCon * nic1 = [[NiCon alloc]init];
        
        // 
        [cams setValue:nic1 forKey:@"nicon1"];
        NSLog(@"nicon1:  %@", cams._nicon1);
    //    return NO;
    //        2019-03-11 16:49:44.899991+0800 test[2256:72136]  key : nicon1   
    //    2019-03-11 16:49:44.900311+0800 test[2256:72136] nicon1:  (null)
    
    //    return YES;
    //    2019-03-11 16:44:29.408502+0800 test[2112:64508] nicon1:  
    //    2019-03-11 16:44:29.408724+0800 test[2112:64508] nicon2:  
    
        // 
        [cams setValue:nic1 forKey:@"nicon1"];
        NSLog(@"nicon1:  %@", cams.isNicon1);
    
    //    return NO;
    //        2019-03-11 16:49:44.899991+0800 test[2256:72136]  key : nicon1   
    //    2019-03-11 16:49:44.900311+0800 test[2256:72136] nicon1:  (null)
    
    //    return YES;
    //    2019-03-11 16:44:29.408502+0800 test[2112:64508] nicon1:  
    //    2019-03-11 16:44:29.408724+0800 test[2112:64508] nicon2:  
    
    }
    
    이상의 테스트에서 +(BOOL)accessInstanceVariablesDirectly를 검증하였습니다.반환 값이 YES(기본값)로 설정되어 있으면 런타임 시 속성에 대한 Set 메서드를 찾을 수 없는 경우key,_iskey, key, iskey의 순서대로 구성원 변수를 검색합니다. NO로 설정하면 KVC 검색을 비활성화합니다. set을 찾지 못하면 get 방법은 이상을 던집니다.
    KVC의 setValue:forKeyPath:객체의 중첩 속성을 설정하려면 다음과 같이 하십시오.
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        Cameras* cams = [[Cameras alloc]init];
        NiCon * nic1 = [[NiCon alloc]init];
        
        // keyPath 
        [cams setValue:@" X525" forKeyPath:@"nicon1.devName"];
        NSLog(@"nicon1.devName:  %@", [cams valueForKeyPath:@"nicon1.devName"]);
    //  test[1380:36444] nicon1.devName:   X525
        
        // keyPath 
        [cams setValue:@" X525" forKeyPath:@"nicon2.devName"];
        NSLog(@"nicon2.devName:  %@", [cams valueForKeyPath:@"nicon2.devName"]);
    // test[1540:43465] nicon2.devName:   X525
    
    이를 통해 알 수 있듯이 KVC는 공유와 사유의 플러그인 속성에 대해서도 두려워하지 않는다. 하하가 이렇게 강하다!
    KVC를 사용한 키 값 검증: - (BOOL)validateValue: (inout id nullable * nonnnull) ioValue forKey: (NSString *) inKey error: (out NSError **) outError;
    //NiCon.m
    @implementation NiCon
    
    -(BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError{
        
        return [inKey isEqualToString:@"devNO"];
    }
    
    
    
    
    //viewController.m
    
        NSNumber * num = [NSNumber numberWithInteger:1011];
        if ([cams validateValue:&num forKey:@"nicon2.devNO" error:nil]) {// KVC 
            
            [cams setValue:num forKeyPath:@"nicon2.devNO"];
            NSLog(@"nicon2.devNO:  %@", [cams valueForKeyPath:@"nicon2.devNO"]);
            //log: test[6716:263169] nicon2.devNO:  1011
        }
    
    모델 및 사전 상호 전환:
        Cameras* cams = [[Cameras alloc]init];
        // 
        NSArray * modelKeys = @[@"devName", @"devNO"];
        NSDictionary * modelDic = [[cams valueForKey:@"nicon2"] dictionaryWithValuesForKeys:modelKeys];    NSLog(@"modelDic:  %@", modelDic);
    /*    2019-03-12 09:53:33.489429+0800 test[6716:263169] modelDic:  {
            devNO = 1011;
            devName = "\U5c3c\U5eb7X525";
        }
    */
    
    // 
        NiCon * nicon3 = [[NiCon alloc]init];
        [nicon3 setValuesForKeysWithDictionary:modelDic];
        NSLog(@"devName: %@   devNO:  %@",nicon3.devName, [nicon3 valueForKey:@"devNO"]);
    // 2019-03-12 09:53:33.489696+0800 test[6716:263169] devName:  X525   devNO:  1011
    
    KVC는 확실히 강하지만 만사에 도가 있기 때문에 지나치면 안 된다. 그렇지 않으면 그 반대의 결과를 초래할 수 있다.

    좋은 웹페이지 즐겨찾기