“屬性”(property)是Objective-C的一項(xiàng)新特性瘸羡,用于封裝對(duì)象中的數(shù)據(jù)。有兩大概念:ivar(實(shí)例變量)在辆、(存)取方法工闺。
@property = ivar + getter (+ setter);
// 只讀屬性只有g(shù)etter
property 在 runtime 中是 objc_property_t 定義如下:
typedef struct objc_property *objc_property_t;
struct property_t {
const char * name;
const char * attributes;
};
name
就是屬性的名稱,attributes
包括:類型温峭,內(nèi)存語(yǔ)義猛铅,原子性,和對(duì)應(yīng)的實(shí)例變量凤藏,但是其實(shí)并不是這四項(xiàng)都會(huì)有奸忽。舉個(gè)??:
@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
這里面關(guān)鍵的是屬性的類型,對(duì)于對(duì)象類型的揖庄,可以使用isKindOfClass
來(lái)判斷月杉,但是對(duì)于數(shù)據(jù)類型,就可以使用attributes中的類型來(lái)判斷抠艾。列舉常見一些類型:
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
完成屬性定義后,編譯器會(huì)自動(dòng)編寫訪問(wèn)這些屬性所需的方法桨昙,此過(guò)程叫做“自動(dòng)合成”(autosynthesis)检号。這個(gè)過(guò)程由編譯器在編譯期執(zhí)行。
@property只是聲明了一個(gè)屬性蛙酪,具體的實(shí)現(xiàn)有兩個(gè)對(duì)應(yīng)的詞齐苛,
- @synthesize:編譯器自動(dòng)添加 setter 方法和 getter 方法
- @dynamic:禁止編譯器自動(dòng)添加 setter 方法和 getter 方法
如果 @synthesize 和 @dynamic 都沒寫,那么默認(rèn)的就是
@syntheszie var = _var;
@syntheszie 的使用場(chǎng)景
手動(dòng)實(shí)現(xiàn)了 setter 方法和 getter (或者重寫了只讀屬性的 getter 時(shí))
@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
實(shí)現(xiàn)在 @protocol 中定義的屬性
@protocol TestProtocol <NSObject>
@property (nonatomic,assign) NSInteger age;
@end
@interface Test : NSObject<TestProtocol>
@end
@implementation Test
@synthesize age = _age;
//@synthesize age; // 成員變量名稱就是 age
@end
重寫父類的屬性時(shí)
@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