@property
@Property是聲明屬性的語(yǔ)法呀打。
@Property可以快速方便的為實(shí)例變量創(chuàng)建存取器。
允許我們通過(guò)點(diǎn)語(yǔ)法使用存取器糯笙。
存取器(accessor):指用于獲取和設(shè)置實(shí)例變量的方法贬丛。用于獲取實(shí)例變量值的存取器是getter,用于設(shè)置實(shí)例變量值的存取器是setter给涕。
創(chuàng)建存取器
1. 使用get/set方法創(chuàng)建存取器
- 聲明
// Man.h
#import <Foundation/Foundation.h>
@interface Man : NSObject
{
// 實(shí)例變量
NSString *name;
NSString *sex;
}
// setter
- (void)setName:(NSString *)newName;
// getter
- (NSString *)name;
// setter
- (void)setSex:(NSString *)newSex;
// getter
- (NSString *)sex;
@end
- 實(shí)現(xiàn)
// Man.m
#import "Man.h"
@implementation Man
// setter
- (void)setName:(NSString *)newName
{
name = newName;
}
// getter
- (NSString *)name
{
return name;
}
// setter
- (void)setSex:(NSString *)newSex
{
sex = newSex;
}
// getter
- (NSString *)sex
{
return sex;
}
@end
- 存取器的使用(使用方括號(hào)的語(yǔ)法給存取器發(fā)送消息)
Man *man = [[Man alloc] init];
[man setName:@"Jeep Cherokee"];
[man setSex:@"男"];
NSLog(@"The man name is %@ and the Sex is %@",[man name],[man sex]);
2. 使用@Property創(chuàng)建存取器
- 聲明
// Man.h
#import <Foundation/Foundation.h>
@interface Man : NSObject
@property (nonatomic,strong)NSString *name;
@property (nonatomic,strong)NSString *sex;
@end
-
實(shí)現(xiàn)
使用@Property就不必單獨(dú)聲明實(shí)例變量了豺憔。因?yàn)樵跊](méi)有顯示提供示例變量聲明的前提下额获,系統(tǒng)會(huì)自動(dòng)幫你生成實(shí)例變量。
當(dāng)我們同時(shí)重寫了setter and getter方式時(shí)恭应,系統(tǒng)會(huì)報(bào)錯(cuò)抄邀,原因是找不到實(shí)例變量。其解決方法: 在.m的文件中使用@synthesize
// Man.m
#import "Man.h"
@implementation Man
@synthesize name = _name;
@synthesize sex = _sex;
// setter
- (void)setName:(NSString *)name
{
_name = name;
}
// getter
- (NSString *)name
{
return _name;
}
// setter
- (void)setSex:(NSString *)sex
{
_sex = sex;
}
// getter
- (NSString *)sex
{
return _sex;
}
@end
-
@synthesize name = _name
_name是成員變量
name是屬性
作用是告訴編譯器name屬性為_(kāi)name實(shí)例變量生成setter and getter方法的實(shí)現(xiàn)
name屬性的setter方法是setName,它操作的是_name這個(gè)變量昼榛。
在@synthesize中定義與變量名不同的setter和getter的命名境肾,以此來(lái)保護(hù)變量不會(huì)被不恰當(dāng)?shù)脑L問(wèn)。
@property的特性
1. 原子性
atomic(默認(rèn)):atomic意為操作是原子的胆屿,意味著只有一個(gè)線程訪問(wèn)實(shí)例變量(生成的setter和getter方法是一個(gè)原子操作)奥喻。atomic是線程安全的,至少在當(dāng)前的存取器上是安全的非迹。它是一個(gè)默認(rèn)的特性环鲤,但是很少使用,因?yàn)楸容^影響效率憎兽。
nonatomic:nonatomic意為操作是非原子的冷离,可以被多個(gè)線程訪問(wèn)。它的效率比atomic快纯命。但不能保證在多線程環(huán)境下的安全性酒朵,開(kāi)發(fā)中常用。
2. 存取器控制
readwrite(默認(rèn)):readwrite是默認(rèn)值扎附,表示該屬性同時(shí)擁有setter和getter蔫耽。
readonly: readonly表示只有g(shù)etter沒(méi)有setter。
有時(shí)候?yàn)榱苏Z(yǔ)意更明確可能需要自定義訪問(wèn)器的名字
@property (nonatomic, setter = mySetter,getter = myGetter ) NSString *name;
@property (nonatomic,getter = isHidden ) BOOL hidden;
3. 內(nèi)存管理
assign(默認(rèn)):assign用于值類型留夜,如int匙铡、float、double和NSInteger碍粥,CGFloat等表示單純的復(fù)制鳖眼。還包括不存在所有權(quán)關(guān)系的對(duì)象,比如常見(jiàn)的delegate嚼摩。
retain:在setter方法中钦讳,需要對(duì)傳入的對(duì)象進(jìn)行引用計(jì)數(shù)加1的操作。
strong:strong是在IOS引入ARC的時(shí)候引入的關(guān)鍵字枕面,是retain的一個(gè)可選的替代愿卒。表示實(shí)例變量對(duì)傳入的對(duì)象要有所有權(quán)關(guān)系,即強(qiáng)引用潮秘。strong跟retain的意思相同并產(chǎn)生相同的代碼琼开,但是語(yǔ)意上更好更能體現(xiàn)對(duì)象的關(guān)系。
weak:在setter方法中枕荞,需要對(duì)傳入的對(duì)象不進(jìn)行引用計(jì)數(shù)加1的操作柜候。
copy:與strong類似搞动,但區(qū)別在于copy是創(chuàng)建一個(gè)新對(duì)象,strong是創(chuàng)建一個(gè)指針渣刷,引用對(duì)象計(jì)數(shù)加1鹦肿。
@synthesize
@synthesize是為屬性添加一個(gè)實(shí)例變量名,或者說(shuō)別名辅柴。同時(shí)會(huì)為該屬性生成 setter/getter 方法狮惜。
如果某屬性已經(jīng)在某處實(shí)現(xiàn)了自己的 setter/getter ,可以使用 @dynamic來(lái)阻止 @synthesize 自動(dòng)生成新的 setter/getter 覆蓋。
當(dāng)在 protocol 中聲明并實(shí)現(xiàn)屬性時(shí)碌识。協(xié)議中聲明的屬性不會(huì)自動(dòng)生成setter和getter碾篡,需要使用@synthesize生成setter和getter。 [UIApplicationDelegate window] 就是個(gè)典型的例子筏餐。
@property有兩個(gè)對(duì)應(yīng)的詞开泽,一個(gè)是 @synthesize,一個(gè)是 @dynamic魁瞪。如果 @synthesize和 @dynamic都沒(méi)寫穆律,那么默認(rèn)的就是@syntheszie var = _var;
當(dāng)我們同時(shí)重寫了setter and getter方式時(shí),需要在.m的文件中使用@synthesize
// Man.m
#import "Man.h"
@implementation Man
@synthesize name = _name;
@synthesize sex = _sex;
// setter
- (void)setName:(NSString *)name
{
_name = name;
}
// getter
- (NSString *)name
{
return _name;
}
// setter
- (void)setSex:(NSString *)sex
{
_sex = sex;
}
// getter
- (NSString *)sex
{
return _sex;
}
@end
-
@synthesize name = _name
_name是成員變量
name是屬性
作用是告訴編譯器name屬性為_(kāi)name實(shí)例變量生成setter and getter方法的實(shí)現(xiàn)
name屬性的setter方法是setName,它操作的是_name這個(gè)變量导俘。
在@synthesize中定義與變量名不同的setter和getter的命名峦耘,以此來(lái)保護(hù)變量不會(huì)被不恰當(dāng)?shù)脑L問(wèn)。
@dynamic
@dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實(shí)現(xiàn)旅薄,不自動(dòng)生成辅髓。(當(dāng)然對(duì)于 readonly 的屬性只需提供 getter 即可)。
假如一個(gè)屬性被聲明為 @dynamic var少梁,然后你沒(méi)有提供 @setter方法和 @getter 方法洛口。編譯的時(shí)候沒(méi)問(wèn)題,但是當(dāng)程序運(yùn)行到 instance.var = someVar凯沪,由于缺 setter 方法會(huì)導(dǎo)致程序崩潰第焰;
或者當(dāng)運(yùn)行到 someVar = var 時(shí),由于缺 getter 方法同樣會(huì)導(dǎo)致崩潰妨马。
編譯時(shí)沒(méi)問(wèn)題挺举,運(yùn)行時(shí)才執(zhí)行相應(yīng)的方法,這就是所謂的動(dòng)態(tài)綁定烘跺。
// Man.h
#import <Foundation/Foundation.h>
@interface Man : NSObject
@property (nonatomic,strong)NSString *name;
@property (nonatomic,strong)NSString *sex;
@end
// Man.m
#import "Man.h"
@implementation Man
@dynamic name, sex;
@end