温故而知新,继续复习。
OC中可以通过声明属性来省略setter和getter,达到让代码简洁的目的。使用属性时,不需要在接口和m文件中进行实例变量的声明和setter getter的实现,系统会自动提供这些,但是如果在接口部分自定义了实例变量,那么将以自定义的为准,系统不会生成实例变量。
语法:采用@property关键字,并且@property不是变量,是方法。
命名:属性名不加下划线,只有实例变量才有下划线。
属性是一对setter和getter方法,属性类型是setter方法中的参数类型,是getter方法中的返回值类型。
特性:
1.读写性(readonly,readwrite,setter =,getter =)
readonly:只读状态,通知编译器,属性只生成getter方法,不生成setter方法。
readwrite:读写状态,通知编译器,属性既生成setter方法,也生成getter方法。
setter =/getter =:方法重命名。setter = set://getter = get:。
2.原子性(atomic,nonatomic)
atomic:原子性。默认修饰符,保证了实例变量在多线程情况下访问是安全的, 通过不断加锁解锁实现在同一时刻实例变量只能被一个线程访问。但是不断的加锁解锁会消耗大量的CPU性能。
nonatomic:非原子性。与atomic相反。
3.语义(assign,retain,copy)
语义不同,直接决定了属性对应的setter,getter方法内部实现的不同。
assign:修饰的属性是非对象类型,并且assign是默认的语义特性。
retain:所有对象类型的属性,都可以用retain来修饰。
copy:也是用来修饰对象类型的属性,但是一定要保证代表属性类型的这个类必须接收了NSCopying,而且实现了copyWithZone:方法。字符串通常用copy来修饰。
语义特性涉及到了OC里内存管理的知识。先上代码:
1 @synthesize height = _height; 2 - (void)setHeight:(CGFloat)height 3 { 4 _height = height; 5 } 6 - (CGFloat)height 7 { 8 return _height; 9 } 10 @synthesize school = _school; 11 - (void)setSchool:(NSString *)school 12 { 13 if (_school != school) 14 { 15 [_school release]; 16 _school = [school retain]; 17 } 18 } 19 - (NSString *)school 20 { 21 return [[_school retain] autorelease]; 22 } 23 @synthesize major = _major; 24 - (void)setMajor:(NSString *)major 25 { 26 if (_major != major) 27 { 28 [_major release]; 29 _major = [major copy]; 30 } 31 } 32 - (NSString *)major 33 { 34 return [[_major retain] autorelease]; 35 }
可以发现school属性和major属性与平时看到的setter和getter方法不一样,这是因为school和major是NSString类型,即对象类型,所以用retain或者copy语义修饰,因此需要这样去写,具体的内存管理知识在后面详细记录。
另外需要注意的是,如果没有@synthensize对属性的实现,还重写了setter和getter方法,那么就不会生成相对应的实例变量。换句话,如果重写了setter和getter,必须用@synthensize实现属性,这样才能生成实例变量。
点语法
如果接触过其他的OOP语言,对这个点语法应该很熟悉,点语法就是属性的另一种调用方式,前面一直用getter去访问属性,其实可以直接通过对象名.属性名的方式来访问。