oc課程筆記
堆和棧的區(qū)別
指針是存放在“?!鄙希鴮ο髸r(shí)存放在“堆”上的,訪問對象職能通過指針的方式來訪問。
棧:(stack)存儲(chǔ)的是值類型無ARC (自動(dòng)引用計(jì)數(shù),即原先需要手動(dòng)添加的用來處理內(nèi)存管理的引用計(jì)數(shù)的代碼可以自動(dòng)地由編譯器完成)負(fù)擔(dān),由系統(tǒng)自動(dòng)管理,以執(zhí)行函數(shù)單位,空間大小在編譯時(shí)確定(參數(shù)+局部變量)函數(shù)執(zhí)行時(shí),系統(tǒng)會(huì)自動(dòng)分配一個(gè)stack,結(jié)束時(shí)回立即收回,函數(shù)之間通過拷貝值傳遞,大小有限額通過拷貝值來傳遞。所有函數(shù)都存放在棧上。
堆:儲(chǔ)存引用類型對象,創(chuàng)建對象時(shí)由人工手動(dòng)請求,釋放由運(yùn)行時(shí)的arc自動(dòng)釋放,函數(shù)之間通過指針來傳遞,總體無大小限制(受制于系統(tǒng)內(nèi)存)。
?屬性與實(shí)例變量
屬性與實(shí)例變量都是oc的類型成員
屬性(對外訪問):表達(dá)實(shí)例狀態(tài),描述類型對外接口相比直接訪問實(shí)例變量,屬性可以做更多控制。(getter訪問器方法為讀值,setter訪問器方法為賦值)在有屬性的情況下,盡量用屬性訪問,類外一律用屬性訪問,類內(nèi)通過self使用屬性訪問。
實(shí)例變量(對內(nèi)訪問):類外不能訪問實(shí)例變量,只能在類內(nèi)訪問,其命名規(guī)則為_屬性)只有實(shí)例變量,沒有類型變量,實(shí)例變量是跟隨對象存儲(chǔ)子啊堆上的,值類型的實(shí)例變量“內(nèi)嵌”在對象實(shí)例中,跟隨對象實(shí)例內(nèi)存釋放而釋放,引用類型的實(shí)例變量通過指針“引用”在堆上的引用類型實(shí)例,arc針對引用進(jìn)行計(jì)數(shù)管理,自動(dòng)釋放引用計(jì)數(shù)為0的對象
arc環(huán)境:強(qiáng)引用為默認(rèn),弱引用weak起組織循環(huán)引用的作用
函數(shù)成員
函數(shù):代碼段上的可執(zhí)行指令序列,方法是類的成員函數(shù),表達(dá)實(shí)例行為或類行為所有的方法默認(rèn)為共有方法。動(dòng)態(tài)消息分法:方法調(diào)用通過運(yùn)行時(shí)消息分發(fā)實(shí)現(xiàn),在對象上調(diào)用方法為“向?qū)ο蟀l(fā)送消息”
實(shí)例方法:表達(dá)實(shí)例行為,可以訪問當(dāng)前實(shí)例對象成員有(實(shí)例屬性、實(shí)例變量、實(shí)例方法)用“-”表示
類型方法:表達(dá)類型行為,用“+”表示,可以訪問類型方法、靜態(tài)變量,部能訪問實(shí)例成員,其中的self表示當(dāng)前類。
如參數(shù)類型為值,則為傳值方式,如果參數(shù)類型是引用類型,則通過傳指針的方式。方法可以沒有參數(shù),也可以沒有返回值,如果方法有參數(shù),方法名約定包含一個(gè)參數(shù)名,從第二個(gè)參數(shù)開始需要顯示提供外部參數(shù)名(內(nèi)外2種參數(shù)時(shí),第一個(gè)單詞小寫,第二個(gè)單詞首字母大寫)調(diào)用時(shí),第一個(gè)參數(shù)名忽略,但后面但參數(shù)名必須顯示標(biāo)明
初始化器:用于初始化對象實(shí)例或類型,是一個(gè)特殊的函數(shù)分為:
對象初始化器-(id)init 可重載多個(gè),初始化對象實(shí)例時(shí)init通常和alloc搭配使用,在這里alloc在堆上分配適合大小的內(nèi)存,將屬性或者實(shí)例變量的內(nèi)存置0,init調(diào)用父類初始化器([super init]前置調(diào)用),初始化當(dāng)前實(shí)例變量。
類型初始化器+(viod)initialize只能有一個(gè),initialize負(fù)責(zé)類型級別的初始化,在每個(gè)類使用之前被系統(tǒng)自動(dòng)調(diào)用且每個(gè)進(jìn)程周期中只能被調(diào)用一次,子類的initialize會(huì)自動(dòng)調(diào)用父類的initialize。
對象析構(gòu)器-(void)dealloc只能有一個(gè)負(fù)責(zé)釋放對象擁有的動(dòng)態(tài)資源1.arc將對對象屬性引用計(jì)數(shù)減持(自動(dòng)實(shí)現(xiàn))2.釋放不收arc管理的動(dòng)態(tài)內(nèi)存如:malloc分配的內(nèi)存(手動(dòng)實(shí)現(xiàn))3.關(guān)閉非內(nèi)存資源,如文件句柄,網(wǎng)絡(luò)端口等(手動(dòng)實(shí)現(xiàn))dealloc由arc根據(jù)對象引用計(jì)數(shù)規(guī)則,在釋放對象內(nèi)存前自動(dòng)調(diào)用,無法手工調(diào)用,子類的dealloc無法調(diào)用父類的dealloc。
封裝:encapsulation隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié),對外僅提供公共接口訪問
繼承:inheritance一個(gè)類型在另外類型基礎(chǔ)上進(jìn)行擴(kuò)展實(shí)現(xiàn),每個(gè)類只能由一個(gè)基類,子基類自動(dòng)繼承基類的實(shí)例變量、屬性、類方法,其含義為1.成員復(fù)用,子類復(fù)用基類成員2.類型抽象,將子類當(dāng)作父類來使用,所有類的根類為:NSobject.
多態(tài):polymorphism不同類型針對同一行為的不同實(shí)現(xiàn)方式,子類在父類統(tǒng)一行為接口下,表現(xiàn)不同到實(shí)現(xiàn)方式。子類只可以重寫父類方法,方法名相同、參數(shù)不同的oc不支持方法重載,在子類代碼中,可以使用super來調(diào)用基類的實(shí)現(xiàn)。
字符串 NSString:是一個(gè)Unicode編碼16位字符的字符序列,被定義為類,引類型,在拷貝時(shí)具有引用意義。
NSString的初始化方法有三種例如:
NSString *str1 = @"Hello World!";//字面量初始化
NSString *str2 = [[NSString alloc]initWithCString:"Hello World!" encoding:NSUTF8StringEncoding];//初始化器
NSString *str3 = [NSString stringWithCString:"Hello World!" encoding:NSUTF8StringEncoding];//工廠方法
NSString:擁有恒定性,所有的操作方法無法改變字符串本身,都是以返回新值的方式改變。擁有共享機(jī)制,引用計(jì)數(shù)管理對其有特殊的管理規(guī)則。例如:
NSString *str1 = @"Hello World!"與NSString *str4= @"Hello World!"的指針地址是同一個(gè)。
NSMutableString是NSString的子類,其具有可變性,不具有共享機(jī)制,而NSSting作為其父類具有恒定性,有共享機(jī)制。
NSMutableString并不是在原有內(nèi)存上直接增長,而是重新分配一個(gè)更大或更小的緩存容量存放字符。
緩存容量與增長:字符串初始化后,會(huì)分配一個(gè)緩存容量capacity,其長度一般大于字符串的實(shí)際字符數(shù)量,當(dāng)字符串增長時(shí),如果實(shí)際需求大于capacity,會(huì)以2倍方式指數(shù)增漲過程為=====》1,分配新的內(nèi)存2*capacuty。2,將原來堆內(nèi)存上的內(nèi)容拷貝到新的內(nèi)存。3,釋放原來的內(nèi)存。最后事先估計(jì)好capacity的大小,預(yù)先分配好容量,避免以后capacity的增長。
數(shù)組:是一個(gè)有序的元素序列,支持隨機(jī)存取,索引從0開始,索引訪問越界會(huì)拋出運(yùn)行時(shí)異常,與c語言中的數(shù)組不同,NSArray,被定義為class,引用類型,拷貝是具有引用語義
NSArray:的元素必須是對象,是NSObject的子類1,基本數(shù)值類型必須用NSNumber封裝為對象類型后才能放入數(shù)組2,c語言結(jié)構(gòu)類型,必須用NSValue封裝為對象類型后,才能放入數(shù)組3,數(shù)組元素可以是不同對象類型,可能會(huì)有類型不安全(取元素可能取到不同類型)
NSArray:具有常量性,長度和元素指針都不能改變,但指針的對象內(nèi)部可以改變。
數(shù)組的遍歷方式的快慢:
(Fast Enumeration,直接訪問內(nèi)存,優(yōu)化索引檢查)>(NSEnumerator遍歷:索引檢查+動(dòng)態(tài)消息調(diào)用)>(for循環(huán)訪問:索引檢查+動(dòng)態(tài)消息調(diào)用)
數(shù)組在查找“值相等”等對象時(shí)用:indexOfObject(類型需要實(shí)現(xiàn)isEqual)
數(shù)組在查找“指針相等時(shí)”用indexOfObiectIdenticalTo,數(shù)組在排列時(shí)不改變原數(shù)組,而是返回新數(shù)組
可變數(shù)組NSMutableArray:支持更改數(shù)組長度和元素指針,是NSArray的子類NSMutableArray初始化,會(huì)分配一個(gè)緩存容量capacity,一般大于實(shí)際元素?cái)?shù)量,當(dāng)增長時(shí),如實(shí)際需求量大于capacity其會(huì)以近似二倍方式指數(shù)增長,其代價(jià)為:
1,分配新的堆內(nèi)存2*capacity 。2,將原來的堆內(nèi)存上的元素拷貝到新的內(nèi)存。3,釋放原來的內(nèi)存。
盡量避免使用insertObject:atIndex(所有元素后移)和removeObjectAtIndex(所有元素往前移)等操作,因?yàn)闀?huì)改變數(shù)組元素序列,涉及大量內(nèi)存拷貝操作。
NSSet是一個(gè)無序集合,其儲(chǔ)存的對象不能重復(fù),NSSet被定義為class引用類型,拷貝時(shí)具有引用語義。
ARC:(Automatic Reference Counting)時(shí)oc默認(rèn)的內(nèi)存管理機(jī)制,其針對堆上的對象,由編譯器自動(dòng)生成操作引用計(jì)數(shù)的指令(retain或release)來管理對象的創(chuàng)建與釋放。接受ARC管理的對象有:1,oc對象指針。2,Block指針。3,使用_attribute_定義的typedef。不受ARC管理的對象有:1,值類型。2,使用其他方式分配的對象(如malloc分配)。3,非內(nèi)存資源。
對象引用計(jì)數(shù)計(jì)數(shù)增1(retain)操作:1,將對象引用賦值給其他變量或常量。2,將對象引用賦值給其他屬性或者實(shí)例變量3,將對象傳遞給函數(shù)參數(shù),或者返回值。4,將對象加入集合中。
對象引用計(jì)數(shù)減1(release)操作:1,將局部變量或全局變量賦值為nil或其他值。2,將屬性賦值為nil或其他值。3,實(shí)例屬性所在的對象被釋放。4,參數(shù)或局部變量離開函數(shù)。5,將對象從集合中刪除。引用計(jì)數(shù)變?yōu)?時(shí),內(nèi)存自動(dòng)被釋放。
Autorelease Pool(自動(dòng)釋放池):release會(huì)導(dǎo)致對象立即釋放,如果頻繁的釋放,可能會(huì)造成瑣碎的內(nèi)存管理負(fù)擔(dān)。autorelease可以將release的調(diào)用延遲到自動(dòng)釋放池被釋放。當(dāng)結(jié)束時(shí)所有接受autorelease消息的對象會(huì)立即被釋放。
協(xié)議(Protocol):類型的合同約定,只描述外部接口,不提供具體實(shí)現(xiàn)包含:
1,屬性。2,實(shí)例方法。3,類方法。4,初始化器。5,析構(gòu)器。4和5不常用。
不包含實(shí)例變量成員,協(xié)議中定義的屬性本質(zhì)上是訪問器方法,編譯器不會(huì)合成實(shí)例變量。協(xié)議本質(zhì)上是一種類型,可以作為聲明類型,但不能創(chuàng)建實(shí)例。
注意:遵守協(xié)議后卻沒有實(shí)現(xiàn)必選協(xié)議方法以及協(xié)議類型變量被賦值非協(xié)議對象時(shí),oc編譯器會(huì)出現(xiàn)警告實(shí)際上時(shí)錯(cuò)誤。