Objective-C---8---@property KVC

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];
    }



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值