眾所周知,@property是Objective-C語(yǔ)言的關(guān)鍵字,在xcode4.5之前的版本需要與@synthesize配對(duì)使用,之后則可以單獨(dú)使用。作用是通過合成存取方法來(lái)封裝對(duì)象中的數(shù)據(jù),通常被稱為屬性。因此,@property 的本質(zhì)就是ivar(實(shí)例變量) 和 getter/setter(存取方法)。編譯器是根據(jù)Objective-C嚴(yán)格的命名規(guī)范來(lái)生成存取方法的,因此實(shí)例變量前面會(huì)加下劃線(_),gettter方法就是屬性名,setter方法就是在屬性名前面加set。
下面并不打算討論@property的細(xì)節(jié)問題,而是著重說(shuō)明一下@property在遇到@protocol時(shí)的一些小的變化。對(duì)于@protocol,在iOS開發(fā)中見得最多的應(yīng)該是把它用于代理,例如:
UITableView的代理
UITableViewDelegate,UITableViewdataSource,
UIScrollView的代理
UIScrollViewDelegate等等。
而@protocol最重要的還應(yīng)該用于作為接口(或者叫抽象基類)。由于Objective-C語(yǔ)言不存在多重繼承一說(shuō),因此抽象基類很少這樣叫。常被提及的應(yīng)該是面向協(xié)議編程。
關(guān)于@protocol的簡(jiǎn)單使用:
// Parent.h
@protocol Parent <NSObject>
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
// Child.h
@interface Child : NSObject<Parent>{
NSString *name_;
}
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
// Child.m
@implementation Child
- (void)setName:(NSString *)name {
name_ = name;
}
- (NSString *)name {
return name_;
}
@end
以上示例,定義協(xié)議Parent,Child遵從這個(gè)協(xié)議就必須由自己去實(shí)現(xiàn),這是理所應(yīng)當(dāng)?shù)氖虑椤H绻蝗?shí)現(xiàn):
警告信息:Method 'setName:' in protocol 'Parent' not implemented
Method 'name:' in protocol 'Parent' not implemented
意思是:Parent協(xié)議中的方法setName和name沒有實(shí)現(xiàn)
假如
協(xié)議Parent中使用@property呢?協(xié)議中明確說(shuō)明不能聲明成員變量,@property并不是,應(yīng)該說(shuō)并不僅僅是。代碼如下:
// Parent.h
@protocol Parent <NSObject>
@property (copy, nonatomic) NSString *name;
@end
// Child.h
@interface Child : NSObject<Parent>
// 假如這里面什么也不寫
//@property (copy, nonatomic) NSString *name;
// 假如這里面這樣寫是否正確?
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
// Child.m
@implementation Child
@end
答案是:兩種寫法都可以,不過什么也不寫編譯器一定會(huì)發(fā)出警告,這是毋庸置疑的。只是,警告與上面有所不同。
警告信息:Auto property synthesis will not synthesize property 'name' declared in protocol 'Parent'
意思是:Parent協(xié)議中的屬性name不會(huì)被自動(dòng)合成,也就是不會(huì)自動(dòng)合成存取方法和實(shí)例變量。
再次假如
協(xié)議Parent中使用setName和name,Child遵從Parent協(xié)議,但是使用@property來(lái)合成setName和name方法,同樣可行。
因此,結(jié)論是@property是可以在@protocol中使用的,只是由于@protocol特性的限制,@property在@protocol中并不會(huì)合成實(shí)例變量,只會(huì)合成存取方法。因此在@protocol中使用了@property,對(duì)應(yīng)的在遵從此協(xié)議的類中,如果不需要重寫setter和getter的情況寫也使用@property交給編譯器自動(dòng)合成。
注意:@property合成的實(shí)例變量只有自己可以直接訪問,也就是(_XX = ?),如果還有子類繼承Child,則只能通過點(diǎn)語(yǔ)法訪問,或者直接調(diào)用setter和getter方法訪問。
最后針對(duì)Objective-C協(xié)議補(bǔ)充說(shuō)明
1)Protocol:就一個(gè)用途,用來(lái)聲明一大堆的方法(不能聲明成員變量),不能寫實(shí)現(xiàn)
2)只要某個(gè)類遵守了這個(gè)協(xié)議,就擁有了這個(gè)協(xié)議中的所有方法聲明
3)只要父類遵守了某個(gè)協(xié)議,那么子類也遵守
4)Protocol聲明的方法可以讓任何類去實(shí)現(xiàn),protocol就是協(xié)議
5)OC不能繼承多個(gè)類(多繼承)但是能夠遵守多個(gè)協(xié)議,繼承(:),遵守協(xié)議(<>)
6)基協(xié)議:<NSObject>基協(xié)議,是最根本最基本的協(xié)議,其中聲明了很多最基本的方法
7)協(xié)議可以遵守協(xié)議,一個(gè)協(xié)議遵守了另一個(gè)協(xié)議,就可以擁有另一個(gè)協(xié)議中的方法聲明(稱為協(xié)議繼承)