1. 堆和棧
1.1為什么有堆和棧? :
移動設(shè)備的內(nèi)存是有限的,每個App所占的內(nèi)存都有一定限制,所以需要堆和棧來管理內(nèi)存。
1.2 App占用手機(jī)內(nèi)存的行為有:
- 創(chuàng)建一個OC對象
- 定義一個變量
- 調(diào)用一個函數(shù)或者方法
1.3 內(nèi)存管理的范圍和原因:
- 只有OC對象需要內(nèi)存管理,基本數(shù)據(jù)類型不需要進(jìn)行數(shù)據(jù)管理
- OC對象一般存儲在堆里,由于堆內(nèi)存是動態(tài)分配的,所以堆內(nèi)存需要程序員手動回收;非OC對象存儲在棧中,棧內(nèi)存會被系統(tǒng)自動回收。
- 對于對象而言,棧內(nèi)存用于存放對象的指針,堆內(nèi)存用于存放對象
內(nèi)存中的五大區(qū)域
- 棧區(qū)
- 堆區(qū)
- BSS段
- 數(shù)據(jù)段
- 代碼段
- 棧:存儲局部變量,當(dāng)其作用域執(zhí)行完畢之后,就會被系統(tǒng)立即收回
- 堆:存儲OC對象,手動申請的字節(jié)空間,需要調(diào)用free來釋放
- BSS段:未初始化的全局變量和靜態(tài)變量,一旦初始化就會從BSS段中回收掉,轉(zhuǎn)存到數(shù)據(jù)段中
- 數(shù)據(jù)段(常量區(qū)):存儲已經(jīng)初始化的全局變量和靜態(tài)變量,以及常量數(shù)據(jù),直到結(jié)束程序時才會被立即收回
- 代碼段:代碼,直到結(jié)束程序時才會被立即收回
2. 進(jìn)程和線程
- 線程和進(jìn)程的區(qū)別主要在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個進(jìn)程崩潰后,在保護(hù)模式的影響下不會對其他進(jìn)程產(chǎn)生影響,而線程只是一個進(jìn)程中的不同執(zhí)行路徑。
- 線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個線程死掉就等同于整個進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時,耗費(fèi)資源較大,效率要差一些。但對于一些要求同時進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。
- 進(jìn)程屬于資源分配和調(diào)度的單位,而線程是處理機(jī)調(diào)度和分配的單位
- 系統(tǒng)切換線程的代價比切換進(jìn)程要低;
3. 引用和指針
- 引用可以表示指針
- 引用和指針都是實(shí)現(xiàn)多態(tài)效果的手段
- 引用本身是目標(biāo)變量的別名,對引用的操作就是對目標(biāo)變量的操作
- 指針只是一個地址,是指向某個對象的一串內(nèi)存地址。一個引用對象,其實(shí)就是被引用的對象它本身。指針的指向是可以改變的,而引用是不能改變的。
4. 局部變量和全局變量
- 局部變量的生命周期只在代碼塊內(nèi)
- 全局變量貫穿整個程序的生命周期
5. @property、@synthesize、@dynamic
- @property的本質(zhì):
@property = ivar + getter + setter
- ivar是成員變量,以下劃線開頭,property是屬性。
- 使用@synthesize 只有一個目的——給實(shí)例變量起個別名,或者說為同一個變量添加兩個名字。
- 如果要阻止自動合成,記得使用@dynamic。經(jīng)典的使用場景是你知道已經(jīng)在某處實(shí)現(xiàn)了getter/setter 方法,而編譯器不知道的情況。
- @synthesize 的作用:是為屬性添加一個實(shí)例變量名,或者說別名。同時會為該屬性生成 setter/getter 方法。
- @synthesize:如果某屬性已經(jīng)在某處實(shí)現(xiàn)了自己的 setter/getter ,可以使用 @dynamic 來阻止 @synthesize 自動生成新的 setter/getter 覆蓋。
- 內(nèi)存管理:@synthesize 和 ARC 無關(guān)。
- 使用:一般情況下無需對屬性添加 @synthesize ,但一些特殊情形仍然需要,例如protocol中聲明的屬性。
6. +load()和 +initialize()
- load和initialize方法都會在實(shí)例化對象之前調(diào)用,以main函數(shù)為分水嶺,前者在main函數(shù)之前調(diào)用,后者在之后調(diào)用。
- +initialize 方法會在類收到第一個消息時調(diào)用,是一個懶加載的方式,如果一直沒收到消息,則永不調(diào)用。這種設(shè)計節(jié)省了資源
- +load方法是系統(tǒng)根據(jù)方法地址直接調(diào)用,并不是objc_msgSend函數(shù)調(diào)用(isa,superClass);這就決定了如果子類沒有實(shí)現(xiàn)+load方法,那么當(dāng)它被加載時runtime是不會調(diào)用父類的+load方法的,除非父類也實(shí)現(xiàn)了+load方法;
7. OC程序的編譯、鏈接、執(zhí)行
- 在.m文件中寫上符合OC語法規(guī)范的源代碼
生成main.m
- 使用編譯器將源代碼編譯成目標(biāo)文件
命令行 : cc -c mian.m
- 預(yù)處理
- 檢察語法
- 編譯
將 main.m -> main.o
- 鏈接
命令行 :cc mian.o - framework Foundation
告訴編譯器用到了哪些框架,去哪兒找這些框架
生成可執(zhí)行文件 main.o -> a.out
9. @try、@catch、@finally有什么用?
- try可以讓程序拋出異常后不立即崩潰,在處理完異常后可以繼續(xù)執(zhí)行后面的代碼
@try
{
//把可能拋出異常的代碼放在這里
}
@catch(NSException *ex){
//如果拋出異常,則在這里處理
}
@finally
{
//無論是否發(fā)生異常,都會執(zhí)行這段代碼
}
- 當(dāng)@try中的代碼發(fā)生了異常,發(fā)生異常后面的代碼不會執(zhí)行,會立即轉(zhuǎn)到@catch中,如果沒發(fā)生異常,會執(zhí)行完@try后跳過@catch。@catch只會在@try發(fā)生異常時執(zhí)行
- @finally無論在是否發(fā)生異常,都會執(zhí)行@finally里面的代碼
10. 類方法和對象方法
- 類方法中不能訪問屬性,不能調(diào)用對象方法;對象方法中可以直接調(diào)用類方法。
- 類的屬性是存在對象中的,一個類被加載時,并不會創(chuàng)建對象,所以調(diào)用類方法時,是直接訪問內(nèi)存中的代碼段,并沒有屬性可以訪問。
- 類方法需要通過類名調(diào)用,不能用self調(diào)用,self代表類對象。
- 類方法比對象方法更節(jié)約空間,效率更高。
- 當(dāng)方法不需要訪問屬性,也不用調(diào)用其他對象方法,就可以用類方法。
11. instancetype的含義
- instancetype作為返回值時,代表了當(dāng)前這個類的對象
12. static的含義
- static 不能修飾屬性和方法
- static可以修飾方法中的局部變量,如果方法中的局部變量被static修飾,就會變成靜態(tài)變量,會儲存在常量區(qū),當(dāng)方法結(jié)束,不會被回收。
12. self關(guān)鍵字
- self是一個指針,在對象方法中,self指向當(dāng)前對象;在類方法中,self指向當(dāng)前類
- 當(dāng)方法中有和屬性同名的變量,默認(rèn)先使用變量而不是屬性,要想使用屬性,必須調(diào)用self
- 在方法中想調(diào)用當(dāng)前對象的的另一個方法,也需要用到self
- 在類方法中使用self,self代表了當(dāng)前類在代碼段中的地址,可以用在類方法中調(diào)用其他類方法。
13. super的含義
- 在對象方法調(diào)用super,super代表調(diào)用從父類繼承過來的對象方法
- 在類方法調(diào)用super,super代表調(diào)用從父類繼承過來的類方法
14. @private、@protected、@public
- @private修飾的屬性,只能在本類內(nèi)部訪問
- @protected修飾的屬性,只能在本類和子類中訪問(不寫默認(rèn)是@protected)
- @public修飾的屬性,可以在任意地方訪問
- 子類任然可以繼承父類的私有屬性,只不過不能直接訪問父類的私有屬性
- 將屬性定義在@implementation中,外界訪問不到,任何修飾符都無效
15.description
- NSObject中description方法用來打印對象的信息<類名:對象地址>
- 重寫description可以自定義打印信息
16.什么是SEL?
- SEL叫做selector方法選擇器,是一個類
- SEL對象用來存儲一個方法
- 類對象存儲方法的過程:
- 創(chuàng)建一個SEL對象
- 將方法的信息(方法類型,返回值,方法名,方法參數(shù),方法體)存儲在SEL對象中
- 再將SEL對象作為類對象的屬性存儲
SEL s1 = @selector(methodName)
17. 點(diǎn)語法的本質(zhì)
- 當(dāng)點(diǎn)語法在等號的左邊(self.age = xx),會調(diào)用屬性的setter方法
- 當(dāng)點(diǎn)語法在等號的左邊(int a = self.age),會調(diào)用屬性的getter方法