“属性”(property)是Objective-C的一项新特性,用于封装对象中的数据。有两大概念:ivar(实例变量)、(存)取方法。
@property = ivar + getter (+ setter);
// 只读属性只有getter
property 在 runtime 中是 objc_property_t 定义如下:
typedef struct objc_property *objc_property_t;
struct property_t {
const char * name;
const char * attributes;
};
name
就是属性的名称,attributes
包括:类型,内存语义,原子性,和对应的实例变量,但是其实并不是这四项都会有。举个:
@property (nonatomic,copy) NSString *str;
// name:str attributes:T@"NSString",C,N,V_str
@property (atomic,assign) NSInteger num;
// name:num attributes:Tq,V_num
这里面关键的是属性的类型,对于对象类型的,可以使用isKindOfClass
来判断,但是对于数据类型,就可以使用attributes中的类型来判断。列举常见一些类型:
NSInteger,long Tq,N,V_
NSUInteger TQ,N,V_
CGFloat,double Td,N,V_
float Tf,N,V_
int Ti,N,V_
bool TB,N,V_
CGRect T{CGRect={CGPoint=dd}{CGSize=dd}},N,V_rect
CGPoint T^{CGPoint=dd},N,V_point
完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。这个过程由编译器在编译期执行。
@property只是声明了一个属性,具体的实现有两个对应的词,
- @synthesize:编译器自动添加 setter 方法和 getter 方法
- @dynamic:禁止编译器自动添加 setter 方法和 getter 方法
如果 @synthesize 和 @dynamic 都没写,那么默认的就是
@syntheszie var = _var;
@syntheszie 的使用场景
手动实现了 setter 方法和 getter (或者重写了只读属性的 getter 时)
@interface Test : NSObject
@property (nonatomic,copy,readonly) NSString *name;
@property (nonatomic,assign) NSInteger age;
@end
@implementation Test
@synthesize age = _age;
@synthesize name = _name;
- (void)setAge:(NSInteger)age {
_age = age;
}
- (NSInteger)age {
return _age;
}
- (NSString *)name {
return _name;
}
@end
实现在 @protocol 中定义的属性
@protocol TestProtocol
@property (nonatomic,assign) NSInteger age;
@end
@interface Test : NSObject
@end
@implementation Test
@synthesize age = _age;
//@synthesize age; // 成员变量名称就是 age
@end
重写父类的属性时
@interface Super : NSObject
@property(nonatomic,assign) NSInteger age;
@end
@implementation Super
- (instancetype)init {
self = [super init];
if (self) {
_age = 10;
}
return self;
}
@end
@interface Test : Super {
NSInteger _testAge;
}
@end
@implementation Test
@synthesize age = _testAge;
- (instancetype)init{
self = [super init];
if (self) {
_testAge = 20;
}
return self;
}
@end