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