1、Cocoa是什么?Cocoa是使用OC語言編寫的工具包,里面有大量的類庫、結(jié)構(gòu)體,說白了其實(shí)就相當(dāng)于java中的標(biāo)準(zhǔn)API、C++中的標(biāo)準(zhǔn)庫。OC中沒有命名空間的概念,所以使用加前綴來防止命名沖突,因此你會(huì)看到大量的以NS 為前綴的類名、結(jié)構(gòu)體、枚舉等。
2、Cocoa框架由Foundation Kit、App Kit兩部分組成,前者是基礎(chǔ)工具庫,后者主要是UI庫、高級(jí)對(duì)象等。
3、static 標(biāo)識(shí)的類變量定義在接口的外面,類變量只能本類訪問,除非提供類方法給外部訪問這個(gè)類變量。
4、@語法是OC特有的一種語法,C是沒有的。
5、OC中只有類的成員變量才有訪問權(quán)限控制,@public、@protected、@private,默認(rèn)是@protected,類變量、類方法、成員方法是沒有訪問修飾符的,所有的方法都是public的,所有的類變量都是私有的。
6、OC中的類方法只能類調(diào)用,如果使用對(duì)象調(diào)用就會(huì)報(bào)錯(cuò),而java這只是一個(gè)警告而已。
7、OC中定義類的@interface和java中的interface不是一回事,OC的@protocol和java中的interface才是一碼事。@interface跟java和C++ class關(guān)鍵字差不多,在OC和C++中,都習(xí)慣將類定義寫在頭文件里,而java卻根本沒有頭文件的概念,至于為什么有這樣的差別,我想是為了OC和C++編譯器方便,大多數(shù)時(shí)候編譯器只需要知道頭文件類的定義就知道這個(gè)類有哪些屬性和方法了。
8、get為前綴的方法在OC中有特殊的意義,所以盡量使用成員變量名稱來作為getter方法的函數(shù)名。
9、OC是動(dòng)態(tài)語言,所以即便是@interface中沒有定義的方法在.m文件中實(shí)現(xiàn)了也是OK的,一般我們都是給別人提供頭文件,這種情況就相當(dāng)于把方法變相的私有化了,對(duì)于我這種喜歡在寫代碼過程中隨時(shí)加方法但又不想動(dòng)頭文件的人來說還是比較爽的。
10、在OC中所有對(duì)象的存取都是用指針,C++中還有引用,OC中沒有,我寧愿你強(qiáng)迫我使用一種方法,也不愿你提供給我兩種方法我卻不知道使用哪一種方法的好。
11、OC的方法定義和調(diào)用算是一大“特色”:
方法的定義:-(返回類型) 方法名:(參數(shù)1類型)參數(shù)1變量 參數(shù)2標(biāo)簽:(參數(shù)2類型)參數(shù)2變量...
[類或者實(shí)例的指針方法名: 參數(shù)1 標(biāo)簽2: 參數(shù)2… …],
為了好看,第一個(gè)參數(shù)一般不加標(biāo)簽名,當(dāng)然,標(biāo)簽名都可以隱藏的,但不建議這樣做,因?yàn)楫?dāng)你接手了一個(gè)離職的人程序,其中的JAVA 程序調(diào)用了一個(gè)有五個(gè)甚至更多的參數(shù)的方法,但是你手里沒有這個(gè)方法的API,那么你很難猜得出來這五個(gè)參數(shù)到底都干什么用的,但是Objective-C調(diào)用的時(shí)候,每個(gè)參數(shù)前面都必須有方法的標(biāo)簽名,這樣你便能很容易的從標(biāo)簽名看出這個(gè)參數(shù)是什么意思。
12、調(diào)用類方法:
[Fraction t];
[[Fraction class] t];
Class clazz=[Fraction class];[clazz t];
class 來自于NSObject,相當(dāng)于JAVA 中的getClass()方法,也就是獲取這個(gè)類的Class 對(duì)象,
clazz 前面沒有*,這是因?yàn)镃lass 已經(jīng)是一個(gè)指針。另外這種嵌套調(diào)用的方式,你也要習(xí)
慣,這就和JAVA 中的A.b().c()沒有什么區(qū)別。
獲取Class 有如下幾種方法:
[類或者對(duì)象 class]
[類或者對(duì)象 superclasss]
NSClassFromString(類名的字符串形式)
你也可以通過如下的函數(shù)把Class 轉(zhuǎn)換為字符串形式:
NSStringFromClass(Class)
13、OC中自定義類最好顯示繼承NSObject,可以獲得alloc、init、release等方法。
14、OC中使用nil表示null,但跟java中的null還是有區(qū)別的,java中調(diào)用null的方法,會(huì)報(bào)臭名昭著的空指針異常,而OC不會(huì),所以在OC你不必再為空指針而煩惱。
15、Cocoa中提供的很多函數(shù)和java中的api有很大的不一樣,java是純面向?qū)ο蟮模械姆椒ǘ急仨氃陬愔卸x,但OC是兼容C語言的,所以C中的面向過程思想在OC中也是行得通的,因此Cocoa中很多東西都不是對(duì)象,而是C語言的函數(shù)、結(jié)構(gòu)體,比如NSLog()。
16、對(duì)象的初始化
前面我們看到實(shí)例化對(duì)象最多的方法是:Fraction *frac=[[Fraction alloc] init];
這跟java不一樣,java對(duì)象創(chuàng)建只需要new一下,同時(shí)調(diào)用構(gòu)造方法(實(shí)際上虛擬機(jī)層面分為兩個(gè)步驟:new對(duì)象,執(zhí)行<init>方法(包含構(gòu)造方法)),但是OC中分為兩步:分配內(nèi)存(同時(shí)給變量賦初值)、初始化。
(1)、alloc 是從NSObject 繼承而來的類方法,用于給對(duì)象分配存儲(chǔ)空間,所有的成員變量在此時(shí)對(duì)確定了自己的內(nèi)存位置,并被賦初值,整數(shù)類型為0,浮點(diǎn)數(shù)為0.0,BOOL 為NO,對(duì)象類型為nil,alloc 方法返回對(duì)象的指針。
(2)、init這個(gè)方法是從NSObject繼承而來的,你可以覆蓋它,當(dāng)然init不是構(gòu)造方法,只是一個(gè)普通方法而已,你甚至可以換成其他方法,只不過我們習(xí)慣在方法名前綴加上init。
還記得java中的構(gòu)造方法沒有返回值吧,所以為了達(dá)到j(luò)ava這種效果:Test t = new Test(2);OC中需要你手動(dòng)在普通方法(相當(dāng)于構(gòu)造方法)中return self。
17、NSObject中的description方法相當(dāng)于java中Object的toString方法,,用于獲取對(duì)象的字符串表示。唯一不同的是OC中需要使用格式化字符串%@,才會(huì)觸發(fā)description被調(diào)用:
Fraction *frac=[[Fraction alloc] init];
NSLog(@"%@",frac);
18、Objective-C 的異常都繼承自NSException,當(dāng)然NSException 本身也繼承自NSObject。使用下面的語句塊進(jìn)行異常捕獲:
@try {
<#statements#>
}
@catch (NSException *exception) {
<#handler#>
}
@finally {
<#statements#>
}
總體來說,OC中的異常體系和java中的異常體系差不多,唯一的差別就是java中有業(yè)務(wù)異常,意思就是說你必須捕獲他,如果不捕獲就會(huì)出現(xiàn)編譯錯(cuò)誤,OC中的異?;旧隙紝儆趈ava中的運(yùn)行時(shí)異常,如果你沒有捕獲,發(fā)生了異常程序就會(huì)崩潰,在一些循環(huán)批任務(wù)中尤其要注意。
18、OC中還有一個(gè)特色那就是他的弱類型id,他可以表示任何對(duì)象,實(shí)際上應(yīng)該是利用了指針地址的通用性,由于OC中操作對(duì)象都必須是指針,而指針本身又是一串地址,所以通過指針可以指向一切不同的對(duì)象。
19、繼承(感覺和java差不多?。?br>
20、反射(這個(gè)和異常一樣,感覺跟java也很像)
21、選擇器(其實(shí)就是C中的函數(shù)指針,以及java中的Method類)
22、類別(Category),擴(kuò)充類的功能,但不可以聲明新的成員變量。
類別的應(yīng)用比較廣泛,譬如:第三方的Objective-C 庫RegexKitLite 就是對(duì)NSString、NSMutableString 做的類別,為Objective-C 的字符類型增加了正則表達(dá)式的功能。
23、協(xié)議@protocol,這個(gè)就是前面說的,相當(dāng)于java中的interface,思想都是一種約定、規(guī)范,只是具體語法不一樣罷了。
24、終于到了內(nèi)存管理了,擦,沒怎么看懂,要好好找個(gè)專題弄懂。
25、字符串
-(BOOL) isEqualToString: (NSString*) s
比較兩個(gè)字符串是否相等,與JAVA 一致的地方是==比較指針,比較對(duì)象是否相同要用到equal 方法。
-(NSMutableString*) appendString: (NSString*) s
這與JAVA 的StringBuffer 的append 沒什么區(qū)別。
26、數(shù)組
Cocoa 使用NSArray 表示數(shù)組,但是它不能存儲(chǔ)基本數(shù)據(jù)類型、enum、struct、nil,只能存儲(chǔ)Objective-C 的對(duì)象。
NSArray *array=[NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];
從這個(gè)類方法arrayWithObjects 的定義可以看出,它使用nil 表示數(shù)組元素結(jié)束,這也是nil 不能存儲(chǔ)在NSArray 中的原因。
NSMutableArray 為長(zhǎng)度可變的數(shù)組,相當(dāng)于JAVA 中的List:
NSMutableArray *mArray=[NSMutableArray arrayWithCapacity: 10];
[mArray addObject: @"Apple"];//添加數(shù)組元素
NSEnumerator *e = [mArray objectEnumerator];//獲取數(shù)組的迭代器,相當(dāng)于JAVA 中的Iterator,reserveObjectEnumerator 用于獲取反轉(zhuǎn)之后的數(shù)組迭代器。與JAVA 一致的地方是你在使用迭代器時(shí),不能對(duì)數(shù)組進(jìn)行添加、刪除操作。
for(NSString *ms in mArray){
NSLog(@"%@",ms);
}
//for-each 快速枚舉為Objective-C 2.0 的新特性,Windows 上的GNUStep 并不支持。
27、字典(哈希表)
NSDictionary 用于存儲(chǔ)key-value 的數(shù)據(jù)結(jié)構(gòu),與JAVA 中的Map 類似。
NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys: @"Apple", @"A", @"Google",@"G", nil];//dictionaryWithObjectAndKeys 后的可變參數(shù),每?jī)蓚€(gè)為一個(gè)value-key,以nil 表示結(jié)束。
NSLog(@"%@",[dic objectForKey: @"A"]);//按照指定的key 查詢value
同樣的有NSMutableDictionary 表示長(zhǎng)度可變的字典。
NSMutableDictionary *mDic=[NSMutableDictionary dictionaryWithCapacity: 10];
[mDic setObject: @"Apple" forKey: @"A"];//添加value-key 對(duì)
for(id key in mDic){
NSLog(@"%@ : %@",key,[mDic objectForKey: key]);
}
//快速迭代的for-each 循環(huán)
28、哈希Set
NSSet 表示以hash 方式計(jì)算存儲(chǔ)位置的集合,與JAVA 中的HashSet 是一致的。在NSSet 中的每個(gè)對(duì)象都有一個(gè)唯一的hash 值,重復(fù)的對(duì)象將只能保留一個(gè)。因此,這引出了Objective-C中的對(duì)象比較問題,這需要你實(shí)現(xiàn)從NSObject 繼承而來的如下兩個(gè)方法:
- (BOOL) isEqual: (id) anObject;
- (NSUInteger) hash;
這與JAVA 的對(duì)象比較沒有什么區(qū)別,兩個(gè)相等的對(duì)象必須有相同的hashCode,所以這兩個(gè)方法必須同時(shí)實(shí)現(xiàn)。
同樣的,NSMutableSet 表示長(zhǎng)度可變的哈希Set。
29、封裝類(相當(dāng)于java的包裝器)
前面的幾個(gè)容器類的對(duì)象都不能存放基本數(shù)據(jù)結(jié)構(gòu)、enum、struct、nil,怎么辦呢?在JAVA中我們知道所有的基本數(shù)據(jù)類型都有對(duì)應(yīng)的封裝類,例如:int---Integer、boolean---Boolean,使用封裝類可以把基本數(shù)據(jù)類型包裝為對(duì)象,而封裝類本身又有方法可以返回原來的基本數(shù)據(jù)類型。Cocoa 使用NSValue 作為封裝類。
NSRect rect=NSMakeRect(1,2,30,50);//這個(gè)是在前面提到過的一個(gè)表示矩形的結(jié)構(gòu)體
NSValue *v=[NSValue valueWithBytes: &rect objCType: @encode(NSRect)];
/alueWithBytes 要求傳入包裝數(shù)據(jù)的地址,也就是變量中存儲(chǔ)的數(shù)據(jù)的首地址,我們依然使用C 語言的&作為地址運(yùn)算符,計(jì)算指針存儲(chǔ)的首地址。
//objCType 要求傳入用于描述數(shù)據(jù)的類型、大小的字符串,使用@encode 指令包裝數(shù)據(jù)所屬的類型。
NSMutableArray *mArray=[NSMutableArray arrayWithCapacity: 3];
[mArray addObject: v];
NSRect rect2;
[[mArray objectAtIndex: 0] getValue: &rect2];
//NSValue 的-(void) getValue: