主要内容:属性、属性的属性、KVC
一、属性
(这里不是最终的写法)
属性是Objective - C 2.0定义的语法,为实例变量提供了setter和getter的默认实现
属性的本质是一对setter和getter语法
好处:能一定程度上简化代码,并增强实例变量的访问安全性
属性的声明:@property关键字
示例:@property NSString * name;
相当于在@interface中声明了
- (void)setName:(NSString *)name;
- (NSString *)name; / / OC中getter方法把get给去掉了,更加简便(经常用的形式)
属性的实现:@synthesize 关键字
示例:@synthesize name = _name ;
相当于在@implementation 中实现了setter和getter方法
- (void)setName:(NSString *)name { _name = name } ;
- (NSString *)name { return _name } ;
示例:定义一个完整的Teacher类,包含实例变量、属性、初始化方法、便利构造器
.h文件
@interface Teacher : NSObject
#pragma mark - 声明属性 / / 这是OC里写在类文件中的注释
@property NSString *name;
@property NSIteger age;
@property CGFloat height;
#pragma mark - 初始化方法
- (instancetype)initWithName:(NSString *)name
age:(NSIteger)age
height:(CGFloat)height;
#pragma mark - 便利构造器
+ (instancetype)teacherWithName:(NSString *)name
age:(NSIteger)age
height:(CGFloat)height;
@end
.m 文件
@implementation Teacher
/ / 一般情况下属性的实现是不写的,除了要同时重写setter、getter方法时必须写(只重写setter或getter方法也不用写)
/* @synthesize name = _name;
@symthesize age = _age;
@synthesize height = _height; */
#pragma mark - 实现初始化方法
- (void)initWithName:(NSString *)name
age:(NSIteger)age
height:(CGFloat)height
{
self = [ super init ] ;
if (self) {
[ self setName:name ] ;
[ self setAge:age ] ;
[ self setHeight:height ] ;
}
return self ;
}
#pragma mark - 实现便利构造器
+ (instancetype)teacherWithName:(NSString *)name
age:(NSIteger)age
height:(CGFloat)height
{
return [ [ Teacher alloc ] initWithName:name age:age height:height ] ;
}
@end
二、属性的属性(attribute)
属性的属性:前面的属性是属于类,后面的属性属于类中的属性
为属性提供了一些关键字用以控制setter、getter的实现细节,这些关键字我们称为属性的属性
attribute分为三大类:
1、读写性控制(readonly、readwrite、setter、getter)
readonly:告诉编译器只声明getter方法(可读不可写)
readwrite:告诉编译器即声明了setter方法又声明了getter方法(可读可写)
注意:readwrite是读写性控制的默认设置
2、原子性控制(nonatomic、atomic)
atomic:setter和getter方法在多线程控访问下是绝对安全的, 即setter和getter内部做了多线程访问处理(原子性控制的默认设置是atomic,但我们一般不用,需要县线程安全时才会使用atomic)
nonatomic:setter和getter内部不会做多线程处理,仅仅是普通的setter、getter方法(速度快,平时最常用的)
3、语义设置(assign、copy、retain)
assign:(内部实现是直接赋值)
示例:@property (nonatomic , assign) NSString *name;
- (void) setName:(NSString *)name
{
_name = name;
}
- (NSString *)name
{
return _name;
}
copy:(setter、getter内部实现会做内存优化)
示例:@property (nonatomic , sopy) NSString *name;
- (void) setName:(NSString *)name
{
if (_name != name) {
[_name release ] ;
_name = [name copy ] ;
}
}
- (NSString *)name
{
return [ [ _name retain ] autorelease] ;
}
retain:(setter、getter内部做也会做内存优化)
示例:@property (nonatomic , retain) NSString *name ;
- (void)setName:(NSString *)name
{
if (_name != name) {
[ _name release ] ;
_name = [ name retain ] ;
}
}
- (NSString *)name
{
return [ [ _name copy ] auto lease ] ;
}
区别:
1、assign:如果属性是非对象类型(如int、float等)属性的语义设置用assign
2、retain:如果属性是对象类型(如NSString、NSMutableArray等),属性的语义设置用copy
3、copy:属性是对象类型且想得到参数的copy,使用copy关键字
点语法
凡是符合系统默认的setter、getter书写格式的方法都可以使用点语法
示例:[ person setName:@" xiaoming " ] ;
等价于 person.name = @" xiaoming " ;
属性是一对setter、getter方法,点语法是另一种调用方式
三、KVC(Key - Value - Coding)
键值编码,是一种间接访问实例变量的方法
key : 用于标示实例变量的值
value : 实例变量所对应的值
修改值的方法:
setValue: forKey
setValue: forKeyPath:
setValueForKeysWithDictionary:
获取值的方法:
valueForKey:
valueForKeyPath:
valueForUndefinedKey:
注意:当key不存在的时候,会执行 setValue : forUndefinedKey:
系统默认实现是抛出一个异常