1.單繼承:繼承是單向的(不能相互繼承)、繼承也是單點的(子類只能由一個父類)。
在類的.h文件中,@interface后的冒號表示繼承關系,冒號左邊的類繼承自冒號右邊的類(沒有特殊說明,一般式NSObject,所有的類最終都繼承自該類)
2.傳遞性:子類具備父類的所有實例變量和方法(不包括私有的變量和方法),并且能通過父類繼承到父父類的實例變量和方法
3.實例變量:實例變量的書寫規則:實例變量的名字遵循駝峰法命名,在實例變量前使用下劃線開頭。
實例變量的可見度:
@public實例變量的可見度的修飾詞,public表示公共的,使用public修飾實例變量可以在類的外部隨意訪問。
@protected表示受保護的可見度,可以在類及其子類中訪問,不能在main中訪問
@private私有的可見度,只能在本類中訪問,不能在其他地方訪問
4.類的方法:
-:減號是方法的類型修飾符,減號表示這個方法只能由對象來調用 (這個消息只能發送給對象)
如果是+號表示這個方法只能由類來調用(這個消息只能發送給類)
[super 方法名]去父類中執行方法的實現
description方法是由系統提供的一種描述對象的是一個實例方法,默認打印一個對象時,會調用該方法,返回類名+對象地址,我們可以重寫這個方法,將若干實例變量拼接為一個字符串返回,這樣我們就可以打印想要的信息
5.方法的返回值:
基本數據類型:int、float、double...
對象類型:類名+*
id或者nstancetype:含義和void 含義一樣,由誰調用這個方法,那么該方法執行完后的返回值類型和調用者的類型一致
6.OC中方法沒有實現時,程序不會馬上崩潰,首先在其繼承樹查找這個方法有沒有實現,然后通過相應代碼在整個工程中查找這個方法有沒有實現,最后再在錯誤處理機制中查找這個方法有沒有實現,要是沒有實現則程序崩潰。
7.#include和@class的區別
#include是C中導入頭文件的指令,#import是OC中導入頭文件的指令,#import可以自動檢測是否產生了循環導入,如果有,則自動斷開其中一條鏈路,而#include本身并不具備這種檢測、規避功能。
@class:@class可以解決循環引入后,斷開某條線路的情況。在聲明文件中,使用@class將類名聲明出來,并不導入該類,在實現文件中,使用#import導入類的頭文件。這樣不僅僅避免了循環引入,而且互相把對類聲明為自己的實例
8.便利構造器:
便利構造器是將創建對象時的alloc、init這兩步操作封裝在一個方法里,以后再創建對象時,只要調用便利構造器即可。便利構造器是一個類方法,由類名調用。便利構造器方法名的命名規則:首字母小寫的類名+參數形容詞、參數類型、參數名。便利構造器可以攜帶0到多個參數(根據具體需求選擇參數個數)。
9.block語法:
在C語言中,我們可以使用函數指針指向一個函數,這樣我們就可以通過函數指針來調用這個函數(將函數名交給函數指針)。
如果函數沒有函數名,也就是匿名函數,匿名函數在C中是不合法的,也無法直接調用或通過指針調用。但是在OC中,我們可以通過block變量來保存這個匿名函數,在之后合適的地方通過block變量名來調用這個函數
定義block變量的方法和定義函數指針的方法一樣,唯一不同的是函數指針使用,block變量使用^將后邊的字符聲明為block變量名
int (^myBlock)(int,int);
將同類型的函數(匿名函數)賦值給block變量:
^int (int a, int b)匿名函數
1."^"將函數聲明為block變量的值,如果沒有托字符,則這個函數無法賦給block變量
2.匿名函數的返回值類型可以省略,但是參數類型和參數的名字不可以省略
myBlock = ^int (int a, int b)
{
return a + b;
};
在block內部可以訪問局部變量和全局變量,但是只能修改全局變量,如果想修改局部變量則需要在局部變量前使用__block來修飾。
10.類的管理:
分類(Category):常用來給拿不到源代碼的類添加新方法或用來管理一個類的方法列表,將功能相似的方法聲明、實現在一個分類中。在分類中只能添加新的方法,不能添加新實例變量
在能拿到源代碼的類中(自定義類),我們可以使用分類來管理功能相似的方法,也可以在分類中給該類添加新方法。對于在分類中聲明的新方法,我們既可以在本類的實現中添加實現方法,也可以新建一個Category的實現標簽,在這個實現標簽中實現新方法
延展(Extension):是用來給類添加私有實例變量、方法的一種管理方式。
我們可以通過延展來給類添加私有的實例變量,該實例變量不管可見度是什么,在類的外部都不能被訪問到,只能在類的內部訪問。
延展和分類的區別:
1.分類中只能添加新方法,不能添加實例變量,延展中可以添加私有方法和私有變量
2.使用分類添加的方法可以在類的外部訪問,使用延展添加的實例變量和方法,只能在類的內部使用,在外部訪問不到
3.分類可以使用一對.h.m文件來管理,延展一般直接在類的.m中添加延展標簽,在延展標簽中寫代碼
協議(Protocol):協議是一套標準(一堆法的聲明),只有.h 件,接受該協議的對象實現協議中定義的方法。
協議就像一張任務清單(或便利貼),上面寫了一堆需要處理的事。清單交給誰,誰就要去完成清單上規定的任務。協議定義好之后,需要有類去遵守這個協議,實現協議中的方法。遵守協議即在.h 件的父類名后寫上<協議名>。實現協議中的方法即在.m 件中實現協議中的方法。相當于給這個類添加了若干個方法。這個類的實例就可以調用這些方法。
@required //使用@required修飾的方法是必須實現的方法
@optional//使用@optional修飾的方法可以選擇性實現
10.代理(delegate):使用場景:凡是某些任務自己不去實現,想讓別人去實現的時候,就可以指定一個代理,讓代理幫你去做。你只需要通知代理去做某某事。聲明一個代理實例變量 id<協議名> _delegated;
11.屬性:屬性是OC2.0之后的新語法,使用屬性編譯器會幫我們生成對應的實例變量和getter和setter方法。使用@propety來聲明屬性。
聲明一個name屬性,編譯器會自動幫我們生成一個在前邊加了下劃線的實例變量:@property NSString *name;
@synthesize在較早的編譯器中,需要使用@synthesize來讓編譯器自動生成屬性所對應實例變量的setter和getter方法的實現部分
使用@dynamic + 屬性名 表示組織編譯器生成屬性(實例變量)的setter和getter方法,此時我們需要手動實現這對兒方法。當我們希望自己手動實現getter、setter方法時,需要先在頭文件中聲明該屬性所對應的實例變量,或者使用@synthesize來將屬性名和實例變量名關聯起來,如果使用@dynamic來強制阻止編譯器自動合成方法實現,則必須手動在頭文件中聲明相關實例變量。如果程序員手動實現了屬性對應實例變量的getter和setter方法,則方法調用時會調用手動實現的方法。
12.屬性的屬性(特征):
第一類:讀寫控制
readonly:只生成getter方法
readwrite:生成getter和setter方法
setter:用來指定setter方法的名字
getter:用來指定getter方法的名字
第二類:原子性控制
atomic:原子安全設置,在多線程環境中,一次只能有一條線程訪問。默認是安全性設置,但是這種設置會降低程序的性能,一般不會考慮
nonatomic:非原子安全設置,setter和getter方法中,并不像atomic一樣添加線程安全控制代碼,而是大大提高程序的性能,但是在多線程環境中,需要考慮線程安全問題
第三類:語義設置
assign:使用assign聲明的屬性對應的實例變量存取器方法的實現,是在方法里直接賦值、取值,并沒有操作內存的引用計數。一般用來將基本數據類型的屬性特征聲明為assign
reatin:使用reatin聲明的屬性對應實例變量存取器的方法的實現,內部會做內存優化處理:修改對象的引用計數。
copy:使用copy聲明的屬性對應的實例變量存取器方法的實現,內部也會做內存優化處理:將對象拷貝一份,然后修改新對象的引用計數(區分深拷貝和淺拷貝)。
一般情況下,將OC中的對象聲明為reatin或copy特征
12.點語法:
點語法:我們可以使用點語法來調用對應實例變量的setter和getter方法。使用點語法,并不是直接訪問了實例變量,而是通過實例變量的存取器方法來給實例變量取值、賦值。
-
KVC:鍵值編碼,一種給對象的實例變量賦值的方法
KVC是一種間接的給實例變量賦值的方法,K表示key表示實例變量(屬性),V表示value是賦給實例變量的值。
kVC常用賦值(修改值)方法:
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setValuesForKeysWithDictionary:
KVC常用獲取值方法:
valueForKey:
valueForKeyPath:
valueForUndefinedKey:
在使用KVC給一個未知的屬性賦值時會調用setValue:forUndefinedKey:方法,該方法默認實現是拋出一個異常(程序崩潰)。我們可以重寫該方法,避免程序崩潰
14.OC中的內存管理:
OC作為一門編程語言,具備垃圾回收機制,但是在iOS平臺使用引用計數機制
內存管理方式:
1.GC(垃圾回收機制):由系統判斷內存是否需要回收,不需要顯式的去寫內存釋放代碼。
2.MRC(手動管理引用計數):程序員自己手動去寫代碼來記錄引用計數的值,并且控制值的增減。
3.ARC(自動管理引用計數):編譯器在它認為合適的地方為我們添加記錄引用計數增減的代碼,ARC是iOS5之后編譯器的特性,并不是OC的語法特性。
注意:在iOS中有ARC和MRC這兩種內存管理機制,但MAC OS里可以有GC這種機制。
iOS中采用引用計數的機制去管理內存,當你向持有某個對象的時候(擁有對象所有權),你需要使該對象的引用計數+1,當你不再需要持有該對象時,你要把剛剛加上的1再減回去。
當這個對象的引用計數變為0時,表示沒有任何對象持有該對象,則這個時候系統會自動調用該對象的dealloc方法來回收該對象所占用的內存。
我們不能過度釋放對象,因為對象的引用計數變為0時,該對象所在的內存就已經可能被其他數據覆蓋,該指針變成了野指針,向一個野指針發送消息,可能造成程序崩潰,也肯能不崩潰,難以調試。此時我們就可以開啟“僵尸對象”來調試這種錯,開啟該模式后,凡是向已釋放的對象發送消息,程序必然崩潰。僵尸模式下,一個已釋放的對象所占用的內存不會被覆蓋,而且這片內存空間不能被訪問,所以向一個僵尸發送消息,程序一定會崩潰。僵尸模式在app上線時一定要關閉,否則app會被審核拒絕上線。
+alloc:創建出對象,并且把對象的引用計數值加1
-retain:將對象的引用計數加1.不管該對象之前的引用計數是幾,它都l只加1。
-release:將對象的引用計數減1,使用release將person計數減1,變為0,打印時不會顯示0,會直接回收。
-copy操作是將源對象拷貝一份副本,并將副本的引用計數加1,源對象的引用計數保持不變。
-autoreless:在出了自動釋放池之后,將對象的引用計數減1。
如何創建一個自動釋放池
第一種:@autoreleasepool {} 第二種:創建一個自動釋放池對象,從這里開始就是自動釋放池的起始位置 NSAutoreleasePool *autoreleassPool = [[NSAutoreleasePool alloc] init]; 中間是自動釋放池的空間。 釋放自動釋放池對象,也就是設置自動釋放池的結束位置 [autoreleassPool release];