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