Objective-C笔记
1、在編譯一個使用了CPerson類的文件時,如果不需要知道該類的全部細節,只需要知道有一個類名叫CPerson,最好“向前聲明”該類(同理于對一個協議的引用),這樣做也可以避免“循環引用”問題:
例:
@class??CPerson
例:
#import "CShape.h"
#import "CDrawable.h"
@interface??CRectangle : CShape <CDrawable>
2、多用字面量語法,少用與之等價的方法 (NSString/NSNumber/NSArray/NSDictionary)
字面量語法的限制:除了字符串以外,所創建出來的對象必須屬于Foundation框架才行。如果自定義了這些類的之類,則無法用字面量語法創建其對象。
例:
NSString *someString = @"Effective Objective-C 2.0";
NSNumber *someNumber =?@1?;
NSNumber *floatNumber = @2.5f;
NSNumber *boolNumber = @YES;
NSNumber *charNumber = @'a';
NSArray *animals = @[@"cat", @"dog",@"pig"];//若@“dog”為空,程序會拋出異常令應用程序終止執行,達到檢查是否含空字符串的目的
NSArray *dog = animals[1];
NSDictionary *personData = @{@"firstName" : @"Matt", @"lastName" : @"Galloway", @"age" : @28};//一旦有值為nil也會拋出異常
NSDictionary *firstName = personData[@"firstName"];
3、多用類型常量const static,少用#define預處理指令,這樣創建出來的常量有類型信息,便于差錯。
1)若不打算公開某個常量,則應將其定義在使用該常量的實現文件里;
2)在頭文件中使用extern來聲明全局常量,并在相關實現文件中定義其值。
4、用枚舉表示狀態、選項、狀態碼
enum Week {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
enum Week day = Monday;
5、理解“屬性” (屬性用于封裝對象中的數據,保存著數據的實例變量一般通過“存取方法”來訪問)
1)atomic(原子性),如果屬性具備nonatomic特質,則不使用同步鎖;(開發iOS程序中所有的屬性都聲明為nonatomic,原因是:在iOS中使用同步鎖的開銷較大,這會帶來性能問題;但是在開發Mac OS X程序時,使用atomic屬性通常都不會有性能瓶頸。所以在iPhone這種小型設備上,如果沒有使用多線程間的通訊編程,那么nonatomic是一個非常好的選擇。)
2)readwrite(讀寫),擁有“獲取方法”和“設置方法”,由@synthesize實現;
3)readonly(只讀),僅擁有“獲取方法”,由@synthesize實現;
4)assign,“設置方法”只會執行針對“純量類型”(CGFloat、NSInteger等)的簡單賦值操作,不更改索引計數,即setter方法直接賦值,不進行任何retain操作(對基礎數據類型 (NSInteger)和C數據類型(int, float, double, char, 等)使用,否則可能導致內存泄露)
5)strong,設置方法會保留新值,并釋放舊值,然后再將新值設置上去;使用ARC機制時,等同于retain
6)weak,設置方法既不保留新值,也不釋放舊值。此特質同assign類似;使用ARC機制時,等同于assign,對象被釋放時,屬性的值會被設置為nil
7)copy,設置方法并不保留新值,而是將其“拷貝”,建立一個索引計數為1的對象,然后釋放舊對象,即setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再Copy出新的對象,retainCount為1,為了減少對上下文的依賴而引入的機制(對NSString )
例:-(void)setOne:(NSObject *) other
{
if(one != other)
{
[one release];
one = [other copy];
}
}
8)retain,釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1,即setter方法對參數進行release舊值再retain新值,為了解決原類型與環循引用問題(對其他NSObject和其子類)
例:-(void)setOne:(NSObject *) other
{
if(one != other)
{
[one release];
one = [other retain];
}
}
(copy與retain的區別:
copy是創建一個新對象,retain是創建一個指針,引用對象計數加1
copy 到另外一個NSString 之后,地址為不同 ,內容相同,新的對象retain為1 ,舊有對象沒有變化
retain 到另外一個NSString 之后,地址相同(建立一個指針,指針拷貝),內容當然相同,這個對象的retain值+1)
a、property,他可以提供的功能有:提供成員變量的訪問方法的聲明、控制成員變量的訪問權限、控制多線程時成員變量的訪問環境
b、synthesize的理解是:實現property所聲明的方法的定義
c、使用屬性的話,編譯器會自動生成存取方法,并自動向類中添加適當類型的實例變量,并在屬性名前面加下劃線。
d、可用@synthesize語法來指定實例變量的名字;用@dynamic關鍵字則會告訴編譯器:不要自動創建實現屬性所用的實例變量,也不要為其創建存取方法。
6、在對象內部盡量直接訪問實例變量,在對象之外訪問實例變量時總是通過屬性來做?
(筆者強烈建議在讀取實例變量的時候采用直接訪問的形式,而在設置實例變量的時候通過屬性來做)
(在初始化方法及dealloc方法中,總是應該直接通過實例變量來讀寫數據)
直接訪問(_name) 與 屬性訪問(self.name) 的區別:
1)直接訪問速度快,編譯器所生成的代碼會直接訪問保存對象實例變量的那塊內存;
2)直接訪問不會調用“設置方法”,這就繞過了為相關屬性所定義的“內存管理語義”;
3)直接訪問實例變量不會觸發“鍵值觀測”(KVO)通知;
4)通過屬性來訪問有助于排查與之相關的錯誤,因為可以給“設置方法”設置斷點。
7、理解“對象等同性”這一概念
1)按照 == 操作符比較的是兩個指針本身,而不是其所指的對象;
2)應該使用NSObject協議中聲明的“isEqual”:方法來判斷兩個對象的等同性。(“isEqualToString:”、“isEqualToArray:”、“isEqualToDictionary:”)
3)相同的對象必須具有相同的哈希碼,但是兩個哈希碼相同的對象卻未必相同。
8、instancetype和id的異同
1)相同點:
都可以作為方法的返回類型
2)不同點:
instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象;
instancetype只能作為返回值,不能像id那樣作為參數。
9、@selector
1)一種類型 SEL
2)代表你要發送的消息(方法), 跟字符串有點像, 也可以互轉.: NSSelectorFromString() / NSSelectorFromString()
3)可以理解為類似函數指針的東西–是能讓Objective-C動態調用方法的玩意.–是 object-c 的動態后綁定技術 可以通過字符串 訪問的函數指針
4)其實就是消息響應函數—選一個消息響應的函數地址給你的action
5)@selector(function_name) 即取得一個function的id
10、理解objc_msgSend的作用(“傳遞消息”)
1)消息由接收者、選擇子(方法)及參數構成。給某對象“發送消息”也就是相當于在該對象上“調用方法”;
2)發給某對象的全部消息都要由“動態消息派發系統”來處理,該系統會查出對應的方法,并執行其代碼;
3)C語言使用“靜態綁定”(編譯期就能決定運行時所應調用的函數),而objective-c則使用“動態綁定”(所要調用的函數直到運行期才能確定)
4)編譯器看到消息后,會將其轉換為一條標準的C語言函數調用,這個核心函數叫做:objc_msgSend:
id returnValue = [someObject messageName:parameter];
==> id returnValue = objc_msgSend(someObject, @selector(messageName:), parameter);
(該方法需要在接收者所屬的類中搜尋其“方法列表”,如果能找到與選擇子名稱相符的方法,就跳至其實現代碼。若是找不到,那就沿著繼承體系繼續向上查找,等找到合適的方法之后再跳轉。如果最終還是找不到相符的方法,那就執行“消息轉發”操作。)
11、@synthesize和 @dynamic
@property有兩個對應的詞,一個是@synthesize,一個是@dynamic。如果@synthesize和@dynamic都沒寫,那么默認的就是@syntheszie var =?_var;
@synthesize的語義是如果你沒有手動實現setter方法和getter方法,那么編譯器會自動為你加上這兩個方法。
@dynamic告訴編譯器,屬性的setter與getter方法由用戶自己實現,不自動生成。(當然對于readonly的屬性只需提供getter即可)。假如一個屬性被聲明為@dynamic var,然后你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當程序運行到instance.var =someVar,由于缺setter方法會導致程序崩潰;或者當運行到 someVar = var時,由于缺getter方法同樣會導致崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。
12、全局變量,和局部變量再內存占用上有什么區別?
變量可以分為:全局變量、靜態全局變量、靜態局部變量和局部變量。 ?按存儲區域分,全局變量、靜態全局變量和靜態局部變量都存放在內存的靜態存儲區域,局部變量存放在內存的棧區。 ?
按作用域分,全局變量在整個工程文件內都有效;靜態全局變量只在定義它的文件內有效;靜態局部變量只在定義它的函數內有效,只是程序僅分配一次內存,函數返回后,該變量不會消失;局部變量在定義它的函數內有效,但是函數返回后失效。 ?
全局變量和靜態變量如果沒有手工初始化,則由編譯器初始化為0。局部變量的值不可知。 ?
靜態全局變量,只本文件可以用。 ?
全局變量是沒有定義存儲類型的外部變量,其作用域是從定義點到程序結束.省略了存儲類型符,系統將默認為是自動型. ?
靜態全局變量是定義存儲類型為靜態型的外部變量,其作用域是從定義點到程序結束,所不同的是存儲類型決定了存儲地點,靜態型變量是存放在內存的數據區中的,它們在程序開始運行前就分配了固定的字節,在程序運行過程中被分配的字節大小是不改變的.只有程序運行結束后,才釋放所占用的內存. ?
自動型變量存放在堆棧區中.堆棧區也是內存中一部分,該部分內存在程序運行中是重復使用的. ? ? ??
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Objective-C笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AVPlayer播放视频
- 下一篇: Java 拖拽文件到文本框