国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Object-C—KVC

2019-11-14 17:59:24
字體:
來源:轉載
供稿:網友

 

1:使用kvc存取對象屬性

如果要更改對象屬性可以通過什么方法達到呢?

(1)通過setter和getter方法。

(2)屬性。

(3)直接設置實例變量。

今天學習新的一種方法:鍵值編碼-kvc。通過指定要訪問的屬性名字的字符串標識符,可以進行類的屬性的讀取和設置。

鍵值編碼基本調用包括:setValue:forKey:和valueForKey。

栗子:

新建Student類,屬性及成員變量:

@interface Student : NSObject{    @public    NSString * name;    @PRivate    NSString * hobby;}@property(strong,nonatomic) NSString * address;@property(nonatomic) int age;@end

通過setter和getter方法、屬性可以設置屬性:

    Student * stu1 = [Student new];    stu1->name = @"haha";    NSLog(@"%@",stu1->name);            stu1.address = @"street";    //屬性可通過點語法設置    stu1.age = 100;    NSLog(@"address:%@,age:%d",stu1.address,stu1.age);

***下邊通過鍵值編碼kvc設置***

    Student * stu1 = [Student new];    [stu1 setValue:@"kvcName" forKey:@"name"];    NSLog(@"kvc設置name:%@",[stu1 valueForKey:@"name"]);            [stu1 setValue:@18 forKey:@"age"];  //int基本型的需要包裝成oc對象型的    NSLog(@"kvc設置age:%@",[stu1 valueForKey:@"age"]);

通過kvc也可以設置屬性,甚至于private的成員變量也可以設置,Student類中有一個private的成員變量:hobby

    //private的屬性仍然能夠通過kvc設置,所以kvc破壞了面向對象的封裝思想    [stu1 setValue:@"read" forKey:@"hobby"];    NSLog(@"%@",[stu1 valueForKey:@"hobby"]);

既然都可以設置屬性,那么kvc和其他的有什么區別呢?它的使用場景是什么呢?

1:

key返回NSString類型的字符串??梢詥为毺岢鰜恚?/p>

    Student * stu1 = [Student new];    NSString * key = @"name";  //變量 靈活    //[stu1 setValue:@"kvcName" forKey:@"name"];    [stu1 setValue:@"kvcName" forKey:key];    NSLog(@"kvc設置name:%@",[stu1 valueForKey:@"name"]);

這樣key相當于是一個中間變量,無疑大大增強了靈活性。

2:類似id型對象不能點語法的,那么可以通過kvc設置。如:

    id obj = stu1;    //id 不能通過點語法設置屬性    obj.name = @"hehe";    //報錯    [obj setValue:@"idName" forKey:@"name"];    NSLog(@"id設置的name:%@",[obj valueForKey:@"name"]);

2:kvc特點:鍵搜索順序

kvc首先查找的是setter命名的屬性,為證實,重寫setter,如果setter被調用則可以證實。

以Student的name成員變量為例,寫setter方法:

- (void)setName:(NSString *)newName{    NSLog(@"kvc......");    self->name = newName;}

如果被調用則會打印kvc......,

main函數中:

    Student * stu1 = [Student new];    NSString * key = @"name";      [stu1 setValue:@"kvcName" forKey:key];    NSLog(@"kvc設置name:%@",[stu1 valueForKey:@"name"]);

打印結果:

驗證了。。。。。。如果不存在getter呢?也就是說不能用屬性(屬性會自動生成setter和getter方法),那么則會在對象內部查找_key或key的實例變量。

以Student的hobby為例,它不是屬性,用沒有寫setter方法,現在聲明hobby和_hobby,為了驗證寫了一個test方法:

@interface Student : NSObject{    @public    NSString * name;    @private    NSString * hobby;    NSString * _hobby;}@property(strong,nonatomic) NSString * address;@property(nonatomic) int age;- (void)test;

test方法:

- (void)test{    NSLog(@"_hobby = %@",self->_hobby);    NSLog(@"hobby = %@",self->hobby);}

那么當main中hobby通過kvc設置的時候,會發生什么?

    Student * stu1 = [Student new];    [stu1 setValue:@"read" forKey:@"hobby"];    [stu1 test];

按說這是給hobby設置值,打印結果:

結果_hobby上有值,這就證實kvc先查找_key。

注意:使用@property+@synthesize可以自動生成getter和setter,但是如果為其指定非標準的getter和setter,key的搜索則會出現問題。

2:鍵值編碼的鍵路徑

設想以下情況:添加一個Brother類,Student有一個屬性是Brother對象。

@interface Student : NSObject{    @public    NSString * name;    @private    NSString * hobby;    NSString * _hobby;}@property(strong,nonatomic) NSString * address;@property(nonatomic) int age;//添加brother屬性@property(strong,nonatomic)Brother * brother;- (void)setName:(NSString *)newName;- (void)test;@end

而Brother類下有一個屬性broName?,F在有這么一個需求:我需要通過Student給brother下的broName賦值。(不是通過brother)

那么代碼似乎應該這么寫:

    Student * stu1 = [Student new];    Brother * bro1 = [Brother new];    stu1.brother = bro1;    [stu1 setValue:@"兄弟" forKey:@"bro1.broName"];    NSLog(@"%@",[bro1 valueForKey:@"broName"]);      //崩潰

這么寫代碼崩潰,那該怎么寫呢?使用鍵路徑:setValue:forKeyPath:

假設a對象下有一個名為b的屬性,而b中包含了名稱為c的屬性,如果想要從a獲取(或設置)c屬性的內容需要使用如下路徑來描述: b.c (遇到點會解析成路徑)

    Student * stu1 = [Student new];    Brother * bro1 = [Brother new];    stu1.brother = bro1;    [stu1 setValue:@"兄弟" forKeyPath:@"brother.broName"];    NSLog(@"%@",[stu1 valueForKeyPath:@"brother.broName"]);

這樣就可以了,上面的代碼稍作修改:現在brother下有一個brother對象brotherOld屬性,該怎么賦值呢?

@interface Brother : NSObject@property(strong,nonatomic) NSString * broName;@property(strong,nonatomic) Brother * brotherOld;@end

這樣相當于通過兩層去設置值。

    Student * stu1 = [Student new];    Brother * bro1 = [Brother new];    stu1.brother = bro1;            Brother * bigBrother = [Brother new];    bro1.brotherOld = bigBrother;    [stu1 setValue:@"大兄弟" forKeyPath:@"brother.brotherOld.broName"];    NSLog(@"%@",[stu1 valueForKeyPath:@"brother.brotherOld.broName"]);

3:鍵不存在的情況(了解即可)

為一個不存在的鍵setValue forKey的話,會報錯,比如:

[stu1 setValue:@"mei you zhe ge jian" forKey:@"notExist"];    //崩潰

可以實現setValue:forUndefinedKey:

Student下聲明一個字典:NSMutableDictionary * undefinedKeysAndValues可以存到這個字典中(相當于臨時容器)

Student.m文件

//以下兩個方法一般不重寫-(void)setValue:(id)value forUndefinedKey:(NSString *)key{        NSLog(@"呵呵,你所訪問的鍵:%@不存在,你就別想把值:%@放到這個鍵上了,說的就跟你有這個鍵似的!",key,value);    //[self->undefinedKeysAndValues setObject:value forKey:key];}-(id)valueForUndefinedKey:(NSString *)key{    NSLog(@"對不起,沒有這樣的鍵!");    return nil;    //return [self->undefinedKeysAndValues objectForKey:key];}@end

4:字典的valueForKey:

    NSDictionary * dict = @{@"aaa":@"11111111",@"bbb":@"22222222222"};    //NSLog(@"%@",[dict objectForKey:@"aaa"]);    NSLog(@"%@",[dict valueForKey:@"aaa"]);

打印結果:

2015-11-06 19:40:30.445 oc-kvc-001[846:61032] 11111111

Program ended with exit code: 0

本來字典的取值是通過objectForKey,現在也能通過valueForKey取值,說明valueForKey是NSobject的方法,字典繼承自NSobject

5:操作集合

如果對象的某個實例變量為NSArray,而其中存放的又是對象。

Team.h文件:

@interface Team : NSObject@property(strong,nonatomic) NSArray * members;@end

Student.h文件:

@interface Student : NSObject@property(copy,nonatomic) NSString * name;@property(nonatomic) int age;@end

Team下有一個屬性為members的數組,members數組中存放的是Student對象。

        Student * s1 = [Student new];        s1.name = @"學生甲";        s1.age = 1000;                Student * s2 = [Student new];        s2.name = @"學生乙";        s2.age = 28;                Student * s3 = [Student new];        s3.name = @"學生丙";        s3.age = 1100;                Student * s4 = [Student new];        s4.name = @"學生丁";        s4.age = 1400;                NSArray * arr = @[s1,s2,s3,s4];                //對NSArray請求一個鍵值,則會查詢數組中的每一個對象來查找這個鍵,然后將這些結果重新打包為一個NSArray        id ages = [arr valueForKey:@"age"];        NSLog(@"%@",ages);        
//可以取最大值、最小值、求和、平均值、個數。
id maxAge = [arr valueForKeyPath:@"@max.age"]; id minAge = [arr valueForKeyPath:@"@min.age"]; id sumAge = [arr valueForKeyPath:@"@sum.age"]; id avgAge = [arr valueForKeyPath:@"@avg.age"]; id count = [arr valueForKeyPath:@"@count"]; NSLog(@"%@,%@,%@,%@,%@",maxAge,minAge,sumAge,avgAge,count); Team * team = [Team new]; team.members = arr; maxAge = [team valueForKeyPath:@"members.@max.age"]; minAge = [team valueForKeyPath:@"members.@min.age"]; sumAge = [team valueForKeyPath:@"members.@sum.age"]; avgAge = [team valueForKeyPath:@"members.@avg.age"]; count = [team valueForKeyPath:@"members.@count"]; NSLog(@"%@,%@,%@,%@,%@",maxAge,minAge,sumAge,avgAge,count);

 

啊╮(╯▽╰)╭,結束。。。。。。。。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 双流县| 密云县| 都昌县| 洪洞县| 巩义市| 南丰县| 蒙城县| 西平县| 丹东市| 三穗县| 肃北| 宿迁市| 察雅县| 大同县| 囊谦县| 普兰县| 临澧县| 平顶山市| 砀山县| 沭阳县| 宜兰县| 柳江县| 高青县| 瑞丽市| 遂平县| 安岳县| 二连浩特市| 昌宁县| 新化县| 镇沅| 罗甸县| 焦作市| 长兴县| 沈阳市| 哈尔滨市| 晋江市| 都江堰市| 昌江| 平度市| 宣威市| 满洲里市|