iOS開發之KVC

iOS開發之KVC

基本概念

Key-value coding,它是一種使用字符串標識符,間接訪問對象屬性的機制。

不是直接調用getter 和 setter方法。通常我們使用valueForKey 來替代getter 方法,setValue:forKey來代替setter方法。

實例

使用KVC 和不使用 KVC 的對比:

Persion *persion =  [ [Persion alloc] init ];

//不使用KVC
persion.name = @"hufeng" ;

//使用KVC的寫法
[persion  setValue:@"hufeng" forKey:@"name"];

復雜些,多個類之間的調用:
不用 KVC:

Persion *persion =  [ [Persion alloc] init ];

Phone *phone = persion.phone;

Battery *battery = phone.battery;

使用 KVC:

Battery *battery = [persion valueForKeyPath: @"phone.battery" ];

注意- valueForKeyPath 里面的值是區分大小寫的,你如果寫出Phone.Battery 是不行的

序列化

KVC最常用的還是在序列化反序列化對象。

把 json 子串反序列化為 obect:

- (id)initWithDictionary:(NSDictionary *)dictionary {

    self = [self init];

    if (self){

        [self setValuesForKeysWithDictionary:dictionary];

    }

    return self;

}

注意 這里有一個坑 當我們setValue 給一個沒有定義的字典值(forUndefinedKey)時 會拋出NSUndefinedKeyException異常的 記的處理此種情況

KVC驗證

如果讓key 支持 不區分大小寫

下面我們提到一個方法initialize

initialize是在類或者其子類的第一個方法被調用前調用。所以如果類沒有被引用進項目或者類文件被引用進來,但是沒有使用,那么initialize也不會被調用 ,到這里 知道我們接下來要干嘛了吧

+ (void)initialize {
    [super initialize];

    dispatch_once(&onceToken, ^{
        modelProperties = [NSMutableDictionary dictionary];
        propertyTypesArray = @[/* removed for brevity */];
    });
    NSMutableDictionary *translateNameDict = [NSMutableDictionary dictionary];
    [self hydrateModelProperties:[self class] translateDictionary:translateNameDict];
    [modelProperties setObject:translateNameDict forKey:[self calculateClassName]];
}

+ (void)hydrateModelProperties:(Class)class translateDictionary:(NSMutableDictionary *)translateDictionary {
    if (!class || class == [NSObject class]){
        return;
    }

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(class, &outCount);
    for (i = 0; i < outCount; i++){
        objc_property_t p = properties[i];
        const char *name = property_getName(p);
        NSString *nsName = [[NSString alloc] initWithCString:name encoding:NSUTF8StringEncoding];
        NSString *lowerCaseName = [nsName lowercaseString];
        [translateDictionary setObject:nsName forKey:lowerCaseName];
        //注意此處哦
        NSString *propertyType = [self getPropertyType:p];
        [self addValidatorForProperty:nsName type:propertyType];
    }
    free(properties);

    [self hydrateModelProperties:class_getSuperclass(class) translateDictionary:translateDictionary];
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容