1.為什麼main()總是傳回0?可以将main()的傳回結果視為“粗歐文報告”,這樣0就是好消息,沒有錯誤就是成功。
2.消息:消息發送(指令)必須寫在一對括号中,并且必須包含以下兩個部分。
指針,指向接收消息的對象。
方法名,要觸發的方法的方法名。
3.如果在編寫程式時,如聲明指針時,不知道所指對象的準确類型,為此可以使用id類型。id的含義是:指針,并可以指向任意類型的Objective-C對象,e.g.:
id delegate
注意:以上聲明沒有用星号。id已經隐含了星号的作用。
4.在obj-c中,創見對象最常見的途徑就是使用alloc和init,通常會将這兩個消息寫在一行代碼中,并以嵌套的形式連續發送(Apple推薦寫法):
[[NSDate alloc] init];
5.合并存取屬性的便捷方法:
在.h中國,通過@property聲明屬性,如
@property int w;
在impl中,要求編譯器根據@property聲明自動合成(synthesize)出存取方法。如:
synthesize w;
6.方法前的-号表明此方法為執行個體方法,必須通過new才能使用;
方法前的+号表明此方法為類方法,是靜态方法,無需new也能使用。
7.互相擁有的所有權關系導緻相關的對象都無法被釋放。這種情況稱之為“retain循環”(retain cycle)。retain循環是導緻記憶體洩露的常見原因。
8.使用弱引用(weak reference)可以解決retain循環問題。弱引用是不主張所有權的指針。
如:
@interface Asset:NSObject
{
__weak Employee *holder;
}
@property (weak)Employee *holder;
9.當某個由弱引用所指向的對象被釋放時,相應的指針變量會被歸零,即賦為nil。
10.retain計數規則。
前提:“你”代表“目前正在使用的某個類執行個體”。
a.如果用來建立對象的方法,其方法名是以alloc或new開頭的,或者包含copy,那麼你已經得到了該對象的所有權(即可以假設該新對象的retain計數時1,且該對象不在NSAutoreleasePool對象中。)你要負責在不許要使用該對象的時候釋放之。以下時部分常見會“傳輸”所有權的方法:alloc(後會跟一個init方法),copy和mutableCopy。
b.通過任何其他途徑建立的對象(例如便捷方法),你是沒有所有權的(可以假設新對象的retain計數是1,而且該對象已經在NSAutoreleasePool對象中。如果沒有保留該對象,那麼當NSAutoReleasePool對象被“排幹”時,這個對象就會被釋放。)
c.如果你不擁有某個對象,但是要使用該對象的時候,可以向其發送release消息或者autorelease消息(release會使retain計數立刻減1。autorelease會導緻,當NSAutoreleasePool對象被排幹時,再向相應的對象發送release消息)。
d.隻要對象還有至少一個擁有方,該對象就會繼續存在下去(當該對象的retain計數到達0時,就會收到dealloc消息)。
11.記憶體管理,需要經常從局部角度來思考問題,并且以類為分界線,考慮記憶體管理問題,而不是去考慮應用的其他部分時怎麼樣處理某個對象的。
12.為什麼需要一個不能修改的數組NSArray呢?原因有二:
a.保證數組内容的安全。也就是說,程式在使用NSArray對象時,隻能“看”不能“改”。
b.性能考慮。不可修改對象永遠無需拷貝。NSArray的copy方法其實不會做任何額外的工作,僅僅傳回指向自己的指針而已。而NSMutableArray的cpy方法則會制作一份自己的拷貝,并傳回指向新數組對象的指針。
13.NSSet的對象是無序的,是以不能通過索引來通路。隻能向NSSet對象查詢某個對象是否存在,它有一個名為containObject:的方法。
14.在Apple提供的類中,有些覆寫了isEqual:方法。對于這些類,相等的(equal)和相同的(identical)是兩個概念。假如程式有兩個指向NSString對象的指針:
NSString *x = …
NSString *y = …
如果x、y儲存的是完全一樣的位址,則稱這兩個變量是“相同的”。如果x和y所指向的NSString對象包含的是相同的字元,并且排列順序也一樣,則稱這兩個變量是“相等的”。是以,相同的變量一定是相等的,但是相等的變量不一定是相同的。
15.C、C++、Objective-C這類語言的代碼檔案要經過兩步才能完成編譯。首先,預處理器(preprocessor)會讀入并處理整個檔案。接着,預處理器的輸出結果會作為輸入交給真正的編譯器。
16.#include和#import的作用類似:都是先要求預處理器讀取某個檔案,然後将讀入的内容添加至樹出結果。兩者有什麼差別?#import會確定預處理器隻導入特定的檔案一次。#include則允許多次導入同一個檔案。在指定要導入的檔案時,需要為檔案名加上雙引号或者尖括号。如果是雙引号,那麼編譯器會在項目目錄下查找相應的頭檔案。如果是尖括号,那麼編譯器會在預先設定好的目錄下查找相應的頭檔案。
17.#define告訴預處理器:在編譯器看到A之前,使用B替換之。
18.在Objective-C中,有三種途徑可以實作回調。
a.目标-動作(Target-action):在應用開始等待前,要求“當X發生時,向指定的對象發送某個特定的消息。”這裡接收消息的對象是目标(Target),消息的選擇器(selector)是動作(action)。
b.輔助對象(Helper objects):在應用開始等待前,要求“當x發生時,向遵守相應協定的輔助對象發送消息”。委托對象(delegate)和資料源(data source)是常見的輔助對象。
c.通告(Notification):Apple提供了一種稱之為“通告中心(notification center)”的對象。在應用開始等待前,可以告訴通知中心“某個對象正在等待某些特定的通告”。當其中某個通告出現時,向指定的對象發送特定的消息。
19.選擇器:當某個對象收到消息,會向該對象的類進行查詢,檢查是否有與之比對的方法。是以該方法必須非常快速。如果使用方法的實際名稱進行查詢,有可能查詢速度會非常慢。為了提速,編譯器會為每個其接觸過的方法附上一個唯一的數字。這個代表特定方法的唯一數字成為選擇器。
20.Target-action執行個體:
Logger *logger = [[Logger alloc] init];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval :2.0
target:logger
selector:@selector(sayOuch:)
userInfo:nil
repeat:YES];
21.輔助對象方法,依托于協定。
22.通告(Notification)示例:
[[NSNotificationCenter defaultCenter]
addObserver:logger
selector:@selector(zoneChange:)
name:NSSystemTimeZoneDidChangeNotification
object:nil];
上述例子中,該對象通過通告中心将自己注冊為觀察器(observer)。當系統時區設定發生變化時,會向通知中心釋出NSSystemTimeZoneDidChangeNotification通告,然後通告中心會将該通告轉發給相應的觀察器。
23.如何選擇回調方式:
a.對于隻做一件事情的對象,使用目标-動作對(Target-action)。
b.對于功能更複雜的對象,使用輔助對象。最常見的輔助對象類型是委托對象。
c.對于要觸發多個(其它對象中)回調對象(如NSTimeZone),使用通告。
24.回調中的回收處理(防止記憶體洩露):
a.通告中心不擁有其下的觀察器。如果将某個對象注冊為觀察器,那麼通常應該在釋放該對象時,将其移出通告中心。
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self]
}
b.對象不擁有其下的委托對象或資料源對象。如果某個新對象的對象是另一個對象的委托對象或資料源對象,那麼該對象應該在其dealloc方法中取消相應的關聯:
(void)dealloc
{
[windowThatBossesMeAround setDelegate:nil];
[tableViewThatBegsForData setDataSource:nil];
}
c.對象不擁有其目标。如果某個新建立的對象是另一個對象的目标,那麼該對象應該在其dealloc方法中将相應的目标指針賦為0:
(void)dealloc
{
[buttonThatKeepSendingMessages setTarget:nil];
}
25.協定是一組方法聲明,其中的部分方法是必需的,另一些則可選。如果某個對象要扮演特定的角色,就一定要實作相應的必須方法(required method),并選擇實作部分可選方法(optional method)。
26.c語言輔助函數,由于不屬于函數内任何一部分,故應該在.h中位于@interfce之前,在.m中應該位于import之後,@implement之前插入函數詳細實作邏輯。
27.凡是繼承自UIControl類的試圖對象,都可以與使用者進行互動。當螢幕所顯示的視圖包含這類UIControl對象時,其中某個UIControl對象可以成為第一響應對象(first resoponder)。擁有第一響應對象狀态的UIConrol對象,可以處理來自鍵盤的文字輸入及搖動事件(可以實作搖動撤銷這類功能。),并保持這一狀态,直到另一個UIControl對象成為第一響應對象,或者自己收到resignFirstResponder消息。
28.屬性生命周期類型:
a.unsafe_unretained(不需要自動歸零,不需要保留):凡是非對象類型的執行個體變量,都應該使用該特性。
b.strong:要求保留傳入的對象,并放棄原有對象(如果原有對象不再有其它擁有方,就會被釋放)。凡是指向對象的執行個體變量,通常都應該使用strong特性。
c.weak特性,要求不保留傳入的對象。相應的存方法會将傳入的對象直接指派給執行個體變量。如果該對象被釋放,那麼相應的執行個體變量就會被自動賦為nil(如果在聲明指針變量時,使用的是unsafe_unretain特性,那麼當其指向的對象被釋放後,該指針變為懸空指針。向懸空指針發送消息通常會導緻程式崩潰i。)
d.copy:copy特性要求拷貝傳入的對象,并将新對象賦給執行個體變量。
注意:有些類會有兩個版本:一個可修改的,一個不可修改的。無論是哪個版本,copy方法都會傳回不可修改的版本。例如NSMutableString的copy方法會傳回NSString執行個體。
29.關于atomic和nonatomic:通過屬性機制自動生成的存取方法時,如果相關屬性帶有nonatomic,那麼調用速度會快一點點。建議使用nonatomic。因為預設屬性會有atomic特性,是以需要修改。