一、面向對象
- OO(Object Oriented) 面向對象
- OOP(Object Oriented Programmint) 面向對象編程
面向過程編程以事件爲中心,程序圍繞事件,列出了事件的每個步驟,一步一步完成;
面向對象編程以事物爲中心,程序圍繞事物展開,完成事件只是一個任務;
二、面向對象三大特性
- 封裝:將現實世界中存在的某個客體的屬性與行爲綁定在一起,並放置在一外邏輯單元內;
- 繼承:子類自動共享父類數據結構和方法的機制;
- 多態:相同的操作或者函數,過程可作用於多種類型的對象上並能獲得不同的結果;
objective-c是一種能夠完成複雜面向對象編程的簡單的計算機語言,通過提供用於定義類和方法的語法,它擴展了標準的ANSI C程序設計語言。還提供類和接口(任何類都可採用)的動態擴展;
三、類對象的初始化
爲了分配對象,需要發送alloc消息給該消息的類,來獲取一個原始(未初始化)的實例,分配對象時,oc運行時會從應用程序的虛擬內存爲對象分配足夠的內存,除分配內存外,運行時在分配期間還會將所有實例變量設定爲0。
分配原始實例後,必須要對它初始化,初始化的過程將一個對象的初始狀態(即實例變量和屬性)設定爲合理的值並返回對象,初始化的目的在於返回可用的對象,原始初始化init會將內存中的所有對象清0;
1.自定義初始化方法:
創建對象分兩步:分配空間和初始化,初始化的作用就是爲對象賦初始值,初始化方法通常以init開頭;
- super:將消息發送給父類對象;
- self:將消息發送給本對象(self始終代表接收消息的對象);
- [super init]就是將init消息發送給父類對象;
2.指定初始化方法:
通常情況下是指能夠賦值最多的方法;
四、類的屬性及成員變量
屬性是一組設置器與訪問器,與類相似,屬性需要聲明和實現;
屬性的聲明寫在類的.h文件中:
@property int age;
上面的代碼實際上相當於聲明瞭兩個方法
-(void)setAge:(int)age;
-(int)age;
屬性的實現寫在類的.m文件中:
@synthesize age = _age;
該語句的作用是使setAge、以及age方法都是在操作實例變量_age,如果類對象沒有_age實例變量,編譯器會自動聲明一個實例變量_age,並且屬性名是age;
相當於實現了兩個方法:
-(void)setAge:(int)age { _age = age; }
-(int)age{ return _age; }
屬性也可以設置特性:
1.讀寫特性:
readwrite|readonly
getter = 方法名 // 指定訪問器的方法名
setter = 方法名 // 指定設置器的方法名
2.原子性特性:
nonatomic // 非原子性,不保證多線程安全
atomic // 原子性,多線程訪問時較安全
3.setter/getter語義特性:
assign // 直接賦值(適用於基本數據類型int,float,struct)
retain // 賦值時做內存優化 (適用於對象類型)
copy // 複製一個副本 (適用於特殊的對象類型)
屬性和實例變量是不同的,前者是一組方法,後者是一個變量,定義屬性使用@property和@synthesize;
對於屬性的特性定義:基本數據類型使用assign,對象類型使用retain,實現了NSCopying協議的對象使用copy。
五、內存管理
OC採用”引用計數機制”(retainCount)管理對象所佔用的內存;
在OC語言中,NSObject類及子類的實例對象包含一個整形屬性,用來統計當前的引用計數;
實例對象的生命週期:起始於alloc,終止於dealloc;
通過對類發送alloc消息,獲得的實例對象的引用計數賦值爲1,當實例對象的引用計數爲0時,自動對該對象發送dealloc消息;
- copy 製造一個副本,將副本的引用計算賦值爲1,並且擁有副本的所有權
- retain 對象引用計數+1,並擁有對象所有權
- release 對象引用計數-1,並放棄對象所有權
- autorelease 未來某個時間對象引用計數-1,並放棄對象所有權;
指針變量和對象區別聯繫:
對象是放在堆裏面的,而指針變量是放在棧裏面的,唯一的關係是指針變量存的是對象的地址;
非ARC下設置對象的實例屬性
@property(retain, nonatomic) Student *stu;
-(void)setStu:(Student *)stu
{
[stu retain]; // 擁有對象所有權
[_stu release]; // release 之前的_stu,放棄所有權
_stu = stu;
}
dealloc方法在對象引用計數爲0的時候自動被調用,主要用於釋放自身所佔有的資源,永遠不要手動調用dealloc;
-(void)dealloc
{
[_stu release];
[super dealloc];
}
六、自動釋放池
1.使用NSAutoreleasePool類
當創建的對象未來某個時候銷燬時,可以用對象的autorelease方法;對象會將所有權交給最近的NSAutoreleasePool對對象,當池對象drain或者release時,會逐一對池內的對象發送release消,儘量不要使用autorelease,而是使用release;
2.早期版本的自動釋放池
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
// TODO
Student *stu = ...;
[stu autorelease];
[pool release];
3.現版本的創建
@autorelesepool{
Student *stu = ...;
[stu autorelease]; // 將所有權控制交給pool,stu不用手動release;
}
4.便利構造器
+(id) studentWithName:(NSString *)name
{
Student *stu = ...;
return [stu autorelese];
}
內存管理原則:
(1).凡是使用alloc、retain、copy的地方,就要有release或者autorelease與之對應,他們要配對使用;
(2).屬性爲retain或者copy的話,需要在類的dealloc中釋放這個屬性;
(3).便利構造器本身應該包含autorelease(系統框架中的便利構造器已經包含autorelease,所以使用便利構造器獲取得的對象不需要release);
(4).一定不要釋放沒有所有權的對象,不要手動調用dealloc;
在dealloc中輸出NSLog,看dealloc是否執行來判斷對象是否釋放;
關於內存管理,在最新版本的OC中,已經不需要我們手動去release了。
內存檢測工具:
Analyze 內存靜態分析(編譯期)
leaks(Instruments) 內存泄露檢測工具(運行期)