随意细解:OC -- 属性、点语法、KVC

来源:互联网 发布:科比季后赛平均数据 编辑:程序博客网 时间:2024/05/21 06:58

属性

利用属性声明set、get方法。学习阶段,使用MRC,并在 .m 文件中练习get、set方法的完整实现。

读写类属性:

  • readonly 只读 (系统就不会默认生成set方法)

  • readwrite 读写 (如果什么都不写,默认就是可读写)

  • setter 设置指定的set方法默认生成的方法名

  • getter 设置指定的get方法默认生成的方法名

    @property ( getter = isOpen) BOOL open;

原子性控制:

  • nonatomic 没有实现多线程同时访问一个变量的操作保护

  • atomic (如果什么都不写,默认的)添加了对多线程的保护操作。虽然安全,但是大量耗费系统资源,并且这个资源是不必要浪费的,所以一般使用nonatomic。

语义设置:

注意:创建工程 默认是ARC状态(自动管理内存)。在工程的设置中,将Objective-C Automatic Reference Counting 的 YES 改为 NO,手动管理内存 MRC。

get、set方法的完整实现:

  • assign 可以set、get方法的实现,是直接赋值。一般用来声明基本数据类型时候使用。

    默认属性的实现关键字 @synthesize

        @synthesize name = _name;    // 等号前代表声明的属性的名称    // 等号后代表要赋值的成员变量的名称    - (void)setName:(NSString *)name{         _name = name;    }    - (NSString *)name{        return _name;    }
  • retain set、get方法实现,内部实现对内存管理的优化,对象类型声明为retain。

    @synthesize name = _name;    - (void)setName:(NSString *)name{    if ( _name != name){        [_name release];        _name = [name retain];        }    }    - (NSString *)name{        return [[_name retain] autorelease];    }
  • copy 与retain一样,但是声明为copy 有一个先决条件:必须遵守NSCopying协议,并且实现其方法。

    @synthesize name = _name;    - (void)setName:(NSString *)name{    if ( _name != name){        [_name release];        _name = [name copy];        }    }    - (NSString *)name{        return [[_name retain] autorelease];    }

代码演示:

声明属性代表系统默认帮咱们实现了 setter和getter方法,并且实例变量为 _name

@property (nonatomic, retain) NSString *name;

点语法

提供了一个快捷的访问属性一种方式,快捷调用set、get方式。

等号左边调用的是set方法,赋值用的。等号右边调用的是get方法,取值用的。假设有Student类:

stu.name = @"haha";stu.name = stu.sex;NSLog(@"%@", stu.name);

KVC

间接方法,访问stu的属性,做到赋值取值。

运行顺序

  1. 首先看 setValue: 的参数是不是一个对象,因为必须要是对象类型,所以如果不是对象类型,例如基本数据类型,要用NSNumber / NSValue将类型转换为对象。

    [stu setValue:18 forKey:@"age"];

    是错的,应该将NSInteger 转换为 NSNumber:

    NSNumber *num = [NSNumber numberWithInt:18];[stu setValue:num forKey:@"age"];

    或者使用语法糖:

    [stu setValue:@18 forKey:@"age"];

    另外:setValue:后也可以填 nil 。

    [stu setValue:nil forKey:@"age"];

    为了不使程序崩溃,必须在类中重写- (void)setNilValueForKey:(NSString *)key方法:

    - (void)setNilValueForKey:(NSString *)key{      NSLog(@"%@", key);    // 捕获到参数value是空的对应的key}
  2. 判断属性,传入的key的查找顺序为:_key 、 _isKey 、key 、isKey 。如果传入的 key 找不到一样的属性,程序会抛出异常而崩溃,所以应该重写- (void)setValue:(id)value
    forUndefinedKey:(NSString *)key方法。

    [stu setValue:@"ddddd" forKey:@"name1"];

    Student类中没有 name1 的实例变量,所有程序会崩溃。要用间接赋值的保护方法:

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key{    // 捕获间接访问属性时 填错的key和value    NSLog(@"%@  %@", value, key);    // 如果使用间接访问,那么,必须实现这个方法}

常用方法

  • setValue:forKeyPath:方法

    forKeyPath这个方法,相当于跨一级去间接访问属性,是访问本类中属性的属性。通过这个方法去访问的话,需要传入一个路径,按填的这个路径 一级一级的进行查找。

    例如:在Student类中有Phone类的对象作为实例变量

    [stu setValue:@"hello" forKeyPath:@"phone.name"];
  • setValuesForKeysWithDictionary:方法

    通过一个字典去间接赋值一个对象。

    NSDictionary *dic = @{@"name":@"haha", @"sex":@"男"};[stu setValuesForKeysWithDictionary:dic];NSLog(@"%@  %@", stu.name, stu.sex);
0 0