本文共 4290 字,大约阅读时间需要 14 分钟。
1. @property:
1.1. 属性的声明及实现:
之前的@property只是负责setter和getter的声明,需程序员手动实现方法 :
@property int age; @synthesize age = _age;
现在的@property会生成实例变量及setter和getter方法的声明及实现
// 声明的时候:@interface Person : NSObject{ int _age; int _height; double _weight; NSString *_name; }@property int age;@property int height;@property double weight;@property (copy)NSString *name;@end// 实现的时候:@implementation Person// @synthesize会自动实现setter和getter方法@synthesize age = _age; // 会自动访问_age@synthesize name = _name;@synthesize height = _height;@synthesize weight = _weight;@end会完成三件事:
1--声明setter和getter方法
2--生成成员变量(不需要在声明成员变量啦~ ~)
3--实现setter和getter方法
因为@property生成的成员变量是私有的,子类不能直接访问,只能通过setter和getter方法访问 自己声明的成员变量默认是protected,子类可以访问可以将类型一致的写在同一行,用逗号隔开。(尽量不要写在一行)
若是在.h 文件中没有声明任何成员变量,@synthesize age = _age 访问_age时,若不存在,会自动生成一个成员变量_age;可见度为@private。
1.2. 属性的属性/@property的参数:
1.2.1. 有三大类:原子属性,读写属性,set方法处理
1. 原子属性:
atomic:对属性加锁,多线程下线程安全,默认值,速度比nonatomic慢
nonatomic:对属性不加锁,多线程下不安全,但是速度快 (就是普通的setter getter方法)
2. 读写属性:
readwrite:生成getter、setter,默认值
readonly:只生成getter方法
3. set方法处理:
assign:直接赋值,默认值(非对象类型:基本数据类型使用)
retain:先release原来的值,再retain新值(在一个类中有关联其他对象的时候,OC对象类型:NSString,NSArray...使用)- - -内存优化
copy:先release原来的值,再copy新值(所有遵守NSCopying协议的对象使用)- - -内存优化
assign实际生成的setter方法如下:(直接赋值)
- (void)setName:(NSString *)name{ _name = name;}retain实际生成的setter方法如下:
- (void)setName:(NSString *)name{ if(_name != name){ [_name release]; _name = [name retain]; }}copy实际生成的setter方法如下:
- (void)setName:(NSString *)name{ if(_name != name){ [_name release]; _name = [name copy]; }}其他对象类型使用retain NSString,block使用copy吧 在@property后面加属性setter getter 相当于给系统生成的setter和getter方法重命名而已:
@property (nonatomic,assign,setter=isVip:,getter=isVip);
1.2.2. copy和retain的区别:
@property (nonatomic,retain)NSString *name:
retain是在你声明的字符串上进行修改,下面的例子:第一次将str赋给t.name后,对str进行修改,即使不用再次赋值,t.name的内容也会跟着str改变
@autoreleasepool { Teacher *t = [[Teacher alloc] init]; NSMutableString *str = [NSMutableString string]; [str appendString:@"猪八戒"]; t.name = str; [str appendString:@"二师兄"]; NSLog(@"%@",t.name); [t release]; }结果打印显示:
2015-10-07 11:29:43.588 Lesson-OC-8-Property[624:61344] 猪八戒二师兄Program ended with exit code: 0@property (nonatomic,copy)NSString *name:
copy是先拷贝一份str的内容,赋值给t.name,然后对str进行修改的时候,并不会影响t.name的值
@autoreleasepool { Teacher *t = [[Teacher alloc] init]; NSMutableString *str = [NSMutableString string]; [str appendString:@"猪八戒"]; t.name = str; [str appendString:@"二师兄"]; NSLog(@"%@",t.name); [t release]; }结果打印显示:
2015-10-07 11:38:11.722 Lesson-OC-8-Property[691:64925] 猪八戒Program ended with exit code: 0
2. KVC(key value coding):键值编码
KVC是一种间接访问实例变量的方法。
KVC操作方法由NSKeyValueCoding协议提供:
NSObject实现了这个协议,也就是OC中所有的类都支持KVC操作
2.1. 常用的KVC操作方法:
动态设置(修改值):
setValue:属性值 forKey:属性名 (用于简单的路径)
setValue:属性值 forKeyPath:属性路径 (用于复合路径)---类.类.属性
动态读取(获取值):
valueForKey:属性名
valueForKeyPath:属性名
2.2. KVC查找规则:
动态设置属性:
优先考虑调用setter,没有该方法则搜索_age成员变量,如果还是没有,则调用:setValue: forUndefinedKey:方法
动态读取属性:
优先考虑调用age的getter方法,没有该方法则搜索_age成员变量,如果还是没有,则调用:valueForUndefinedKey:方法
注:无论这些方法是私有还是其他,均可正常访问
@autoreleasepool { Person *p = [[Person alloc] init];// p.name = @"Henry"; // 访问私有变量age:---动态设置(简单路径) [p setValue:@"Henry" forKey:@"name"]; // 给name赋值为@"Henry" [p setValue:@"male" forKey:@"sex"]; [p setValue:@28 forKey:@"age"];// 在本题中age是私有变量,但是通过这个方法是可以给age赋值的!!! [p showMessage];// 这个方法用来显示name sex age NSLog(@"%@", [p valueForKey:@"name"]); Account *account1 = [[Account alloc] init]; [p setValue:account1 forKey:@"account"]; p.account.balance = 10.8; //@"account.balance"是因为Person类里包含了实例变量Account *account 要想给account里的balance赋值,需要根据路径找到它 [p setValue:@10.09 forKey:@"account.balance"]; NSLog(@"%.2f", [[p valueForKeyPath:@"account.balance"] floatValue]); // setValuesForKeysWithDictionary:就是用来将一个字典进行赋值 NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Shelock", @"name", @"male", @"sex", @"26", @"age", nil]; [p setValuesForKeysWithDictionary:dic]; NSLog(@"%@", p); [p release]; [account1 release]; }
转载地址:https://blog.csdn.net/Evelynzn/article/details/48946631 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!