【iOS開發(fā)干貨】Objective-C基礎(chǔ)知識(shí)點(diǎn)總結(jié)(一)

個(gè)人主頁:http://hellogod.cn

長文,建議跳躍選擇性閱讀,大約10min可以讀完全文。

iOS開發(fā)

1.目錄

  • 1.個(gè)人學(xué)習(xí)建議
  • 2.知識(shí)點(diǎn)整理
  • 3.下集預(yù)告

iOS這一行,都過了這么多年,還是水分很足,沒有幾個(gè)愿意安安心心查資料寫東西的。雖說博客都是互相抄,但是起碼其他行業(yè)抄的最開始的人是對(duì)的,但是這一行因?yàn)橹形馁Y料少(是的,到現(xiàn)在中文資料也不完善),所以出現(xiàn)很多粗制濫造的,這里經(jīng)過筆者校驗(yàn)之后分享一些相關(guān)知識(shí)。

個(gè)人建議:

  • 入門視頻首選是斯坦福CS193P課程 iOS10, Xcode8 ,Swift 3 - Youtube,白胡子老爺爺在這一行可以稱得上是元老,之前還想出一個(gè)針對(duì)這個(gè)視頻教程的學(xué)習(xí)筆記,后來給鴿了;這里鏈接放了YouTube上的最新視頻,墻內(nèi)的朋友也可以自行百度其他資源,我這里也存了一份百度云(16年的版本iOS9),需要的可以在評(píng)論留下郵箱(某資源論壇既視感???)。

  • 入門教材Programming in Objective-C 6th edition(英文版),這里附上教材PDF下載鏈接,沒有具體考證鏈接合法性,經(jīng)濟(jì)允許建議支持正版。

  • 項(xiàng)目實(shí)戰(zhàn),大學(xué)生的話去實(shí)驗(yàn)室找一個(gè)項(xiàng)目做一做,大概幾個(gè)月也就熟了(最初級(jí)的那種),這里還要感謝當(dāng)初帶我的學(xué)長@子豪學(xué)長——是一個(gè)很讓人佩服的學(xué)長。社會(huì)人士自學(xué)的話可以在在github、碼云上面多找找完整的客戶端試試看。

下面是學(xué)習(xí)OC時(shí)對(duì)于一些知識(shí)點(diǎn)的總結(jié),資料來源互聯(lián)網(wǎng),權(quán)當(dāng)學(xué)習(xí)筆記,參考的資料盡量附上原文鏈接。

2.重要知識(shí)點(diǎn)總結(jié)

其實(shí)下面的每一個(gè)點(diǎn)都可以單獨(dú)行文,這里摘錄其中較為重要的部分,同時(shí)添加鏈接供讀者深度查看。之后可能單獨(dú)領(lǐng)出深究,這里先埋坑。

2.1 繼承關(guān)系

OC中的繼承屬于單繼承,這一點(diǎn)和Java類似。

  • 在Objective-C中super是指向直接父類的指針
  • 而self是指向本身的指針,self就相當(dāng)于java中的this指針。

在Objectiv-C中幾乎所有的類都是繼承自NSObject類,NSObject類中存在大量功能強(qiáng)大的方法。這里不再贅述,詳情可查看

2.2 MVC設(shè)計(jì)模式

MVC

iOS開發(fā)——MVC詳解&Swift+OC

2.3 block

這里搬運(yùn)一下

block定義

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};


struct Block_layout {
    void *isa;
    int flags;
    int reserved; 
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
    /* Imported variables. */
};

有人認(rèn)為OC中block 本質(zhì)應(yīng)該是一個(gè)函數(shù)指針加上一個(gè)對(duì)應(yīng)捕獲上下文變量的內(nèi)存塊(結(jié)構(gòu)體或者類)。
建議參考:
知乎:OC中, block(塊)的本質(zhì)是什么?

2.4 靜態(tài)變量、靜態(tài)常量、全局變量

static

static修飾的變量必須放在@implementation外面或方法中,它只在程序啟動(dòng)初始化一次。

 static int num; 
const

const修飾的變量是不可變的,如果需要定義一個(gè)時(shí)間間隔的靜態(tài)常量,就可以使用const修飾。

 static const NSTimeInterval LMJTimeDuration = 0.5;

如果試圖修改TimeDuration編譯器則會(huì)報(bào)錯(cuò)。

如果我們定義一個(gè)字符串類型的靜態(tài)常量就要注意了,這兩種寫法是一樣的,而且是可以修改的。

 static NSString const * LMJName = @"iOS開發(fā)者公會(huì)";
static const NSString * LMJName = @"iOS開發(fā)者公會(huì)";

這兩種寫法cons修飾的是* LMJName,*是指針指向符,也就是說此時(shí)指向內(nèi)存地址是不可變的,而內(nèi)存保存的內(nèi)容時(shí)可變的。
所以我們應(yīng)該這樣寫:

static NSString * const LMJName = @"iOS開發(fā)者公會(huì)";

當(dāng)我們定義一個(gè)對(duì)象類型常量的時(shí)候,要將const修飾符放到*指針指向符后面。

extern

extern修飾的變量,是一個(gè)全局變量。

extern NSString * LMJName = @"iOS開發(fā)者公會(huì);
extern修飾的變量也可以添加const進(jìn)行修飾:

extern NSString * const LMJName = @"iOS開發(fā)者公會(huì);
此時(shí)全局變量只能被初始化一次
extern定義的全局常量的用法和宏定義類似,但是還是有本質(zhì)上的不同的。 extern定義的全局常量更不容易在程序中被無意竄改。

2.5 NSObject ,Id, instancetype

  • NSObject

NSObject確定對(duì)象類型是繼承于NSObject。很常用。

  • id

可以指向任意類型的objcetive-c的對(duì)象,聲明的對(duì)象具有運(yùn)行時(shí)的特性。并不一定是NSObject對(duì)象。對(duì)于一些不能進(jìn)行類型檢查或者不想檢查的地方,可以使用id,經(jīng)常會(huì)聲明delegate為id類型,在運(yùn)行的時(shí)候載使用respondToSelector:檢查。

  • instancetype

    stack overflow上面所說:“Use instancetype whenever it's appropriate, which is whenever aclass returns an instance of that same class.”
    在instancetype有效的情況下,應(yīng)該盡量去使用instancetype。

id數(shù)據(jù)類型,是一種通用的對(duì)象類型。也就是說,它可以用來存儲(chǔ)屬于任何類的對(duì)象。當(dāng)以這種方式在一個(gè)變量中存儲(chǔ)不同類型的對(duì)象時(shí),在程序執(zhí)行的期間,這種數(shù)據(jù)類型的真正優(yōu)勢就出現(xiàn)了。

instancetype和id的區(qū)別如下(ARC和MRC的講解部分放在后面的2.7中):

區(qū)別1:

在ARC(Auto Reference Count)環(huán)境下:

instancetype用來在編譯期確定實(shí)例的類型,而使用id的話,編譯器不檢查類型, 運(yùn)行時(shí)檢查類型.

在MRC(Manual Reference Count)環(huán)境下:

instancetype和id一樣,不做具體類型檢查

區(qū)別2:

id可以作為方法的參數(shù),但instancetype不可以

instancetype只適用于初始化方法和便利構(gòu)造器的返回值類型

2.6 Copy, strong, retain

先說copy和strong的區(qū)別,這里摘錄一個(gè)例子。

在定義一個(gè)類的property時(shí)候,為property選擇strong還是copy特別注意和研究明白的,如果property是NSString或者NSArray及其子類的時(shí)候,最好選擇使用copy屬性修飾。

為什么呢?這是為了防止賦值給它的是可變的數(shù)據(jù),如果可變的數(shù)據(jù)發(fā)生了變化,那么該property也會(huì)發(fā)生變化。

代碼示例

還是結(jié)合代碼來說明這個(gè)情況

@interface Person : NSObject
@property (strong, nonatomic) NSArray *bookArray1;
@property (copy, nonatomic) NSArray *bookArray2;
@end

@implementation Person
//省略setter方法
@end

//Person調(diào)用
main(){
    NSMutableArray *books = [@[@"book1"] mutableCopy];
    Person *person = [[Person alloc] init];
    person.bookArray1 = books;
    person.bookArray2 = books;
    [books addObject:@"book2"];
    NSLog(@"bookArray1:%@",person.bookArray1);
    NSLog(@"bookArray2:%@",person.bookArray2);
}

我們看到,使用strong修飾的person.bookArray1輸出是[book1,book2],而使用copy修飾的person.bookArray2輸出是[book1]。這下可以看出來區(qū)別了吧。

備注:使用strong,則person.bookArray1與可變數(shù)組books 指向同一塊內(nèi)存區(qū)域 ,books內(nèi)容改變,導(dǎo)致person.bookArray1的內(nèi)容改變,因?yàn)閮烧呤峭粋€(gè)東西;而使用copy,person.bookArray2在賦值之前,將books內(nèi)容復(fù)制,創(chuàng)建一個(gè) 新的內(nèi)存區(qū)域,所以兩者不是一回事,books的改變不會(huì)導(dǎo)致person.bookArray2的改變。

總結(jié)起來,其實(shí)@property的參數(shù)還有很多,主要分為四類:

  • 1、內(nèi)存管理

retain : release舊值,retain新值
assign :直接復(fù)制(缺省值,適用于非OC對(duì)象類型)
copy : release舊值,copy新值

retain assign copy具體實(shí)現(xiàn)
  • 2、讀寫屬性,是否要生成set方法

readaonly :只讀,只生成getter的聲明和實(shí)現(xiàn)
readwrite :可讀可寫,生成setter和getter的生命和實(shí)現(xiàn)(缺省值)

  • 3、多線程管理

nonatomic :性能高,不加鎖,線程不安全(建議使用,開發(fā)常寫)
atomic:性能低,加鎖,線程安全(缺省值)

  • 4、setter和getter方法的名稱

@property (setter = setXxx: ,getter = xxx) int weight;
一般使用在BOOL類型的成員變量 getter = isXxx

2.7 Manually reference Counting和Automatic Reference Counting

** 1.MRC 手動(dòng)管理內(nèi)存(Manual Reference Counting)**

先看一個(gè)例子:

NSNumber對(duì)象myInt被設(shè)置為整數(shù)100,并且程序輸出顯示它的初始計(jì)數(shù)為1。然后,使用addObject:方法將該對(duì)象添加到數(shù)據(jù)myArr中。引用計(jì)數(shù)變成2.將對(duì)象添加到任何類型的集合都會(huì)使該對(duì)象的引用次數(shù)增加。這意味著,如果隨后釋放了添加的對(duì)象,那么數(shù)組中仍然保存這該對(duì)象的有效引用,對(duì)象不會(huì)釋放。

接下來,將myInt賦值給變量myInt2.要注意這個(gè)操作并沒有使myInt對(duì)象的引用次數(shù)增加,這會(huì)給以后造成潛在的麻煩。例如,如果對(duì)myInt的引用次數(shù)減少到0,并且它占用的空間被釋放,那么myInt2將擁有無效的引用對(duì)象(將myInt賦值給myInt2的操作并沒有復(fù)制實(shí)際的對(duì)象,只是指向myInt在內(nèi)存中位置的指針)。

然后通過代碼再來直觀的感受一下。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 只要?jiǎng)?chuàng)建一個(gè)對(duì)象默認(rèn)引用計(jì)數(shù)器的值就是1
        Person *p = [[Person alloc] init];
        NSLog(@"retainCount = %lu", [p retainCount]); // 1

        // 只要給對(duì)象發(fā)送一個(gè)retain消息, 對(duì)象的引用計(jì)數(shù)器就會(huì)+1
        [p retain];

        NSLog(@"retainCount = %lu", [p retainCount]); // 2
        // 通過指針變量p,給p指向的對(duì)象發(fā)送一條release消息
        // 只要對(duì)象接收到release消息, 引用計(jì)數(shù)器就會(huì)-1
        // 只要一個(gè)對(duì)象的引用計(jì)數(shù)器為0, 系統(tǒng)就會(huì)釋放對(duì)象

        [p release];
        // 需要注意的是: release并不代表銷毀\回收對(duì)象, 僅僅是計(jì)數(shù)器-1
        NSLog(@"retainCount = %lu", [p retainCount]); // 1

        [p release]; // 0
        NSLog(@"--------");
    }
//    [p setAge:20];    // 此時(shí)對(duì)象已經(jīng)被釋放
    return 0;
}

MRC內(nèi)存原則

1.需要引用時(shí),+1;不需要引用了,-1;

2.誰創(chuàng)建,誰release;

3.誰retain,誰release;

4.只要調(diào)用了alloc,必須有release(autorelease)

5.成員變量的set方法中需要注意的:基本數(shù)據(jù)不用管,對(duì)象數(shù)據(jù)需要注意。

2.自動(dòng)釋放池(Automatic Reference Counting)
autorelease是一種支持引用計(jì)數(shù)的內(nèi)存管理方式,只要給對(duì)象發(fā)送一條autorelease消息,會(huì)將對(duì)象放到一個(gè)自動(dòng)釋放池中,當(dāng)自動(dòng)釋放池被銷毀時(shí),會(huì)對(duì)池子里面的所有對(duì)象做一次release操作

  • 使用autorelease有什么好處呢

不用再關(guān)心對(duì)象釋放的時(shí)間
不用再關(guān)心什么時(shí)候調(diào)用release

  • autorelease的原理實(shí)質(zhì)上是什么?

autorelease實(shí)際上只是把對(duì)release的調(diào)用延遲了,對(duì)于每一個(gè)autorelease,系統(tǒng)只是把該對(duì)象放入了當(dāng)前的autorelease pool中,當(dāng)該pool被釋放時(shí),該pool中的所有對(duì)象會(huì)被調(diào)用release。

2.8 auto、const和volatile

待補(bǔ)充...

2.9 alloc, init, dealloc, release,new ,retain

簡單地說,alloc分配內(nèi)存空間,init對(duì)該對(duì)象進(jìn)行初始化,這些方法若沒有重寫方法則默認(rèn)繼承自父類。
通常來講,new = alloc + init
Objective-C的對(duì)象在使用完成之后不會(huì)自動(dòng)銷毀,需要執(zhí)行dealloc來釋放空間(銷毀),否則內(nèi)存泄露。下面是一個(gè)簡單的例子。

ClassA *obj1 = [[ClassA alloc] init];

[obj1 hello]; //輸出hello

[obj1 dealloc];

Objective-C采用了引用計(jì)數(shù)(ref count或者retain count)。對(duì)象的內(nèi)部保存一個(gè)數(shù)字,表示被引用的次數(shù)。例如,某個(gè)對(duì)象被兩個(gè)指針?biāo)赶颍ㄒ茫┠敲此膔etain count為2。需要銷毀對(duì)象的時(shí)候,不直接調(diào)用dealloc,而是調(diào)用release。release會(huì)讓retain count減1,只有retain count等于0,系統(tǒng)才會(huì)調(diào)用dealloc真正銷毀這個(gè)對(duì)象。

Objective-C指針賦值時(shí),retain count不會(huì)自動(dòng)增加,需要手動(dòng)retain。


ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //輸出hello
[obj1 release]; //retain count = 2 – 1 = 1
[obj2 hello]; //輸出hello
[obj2 release]; //retain count = 0,對(duì)象被銷毀
alloc & init

Objective-C 內(nèi)存管理——你需要知道的一切

Objective-C內(nèi)存管理教程和原理剖析(一)

2.10 文件操作

待補(bǔ)充...

2.11 分類和協(xié)議

待補(bǔ)充...

2.12 NSString, NSNumber,NSArray,NSDictionary, NSSet 類的主要方法

待補(bǔ)充...

2.13 Cocoa

Cocoa是一種支持應(yīng)用程序提供豐富用戶體驗(yàn)的框架,它實(shí)際上由兩個(gè)框架組成:

  • Foundation框架
  • Application Kit (或AppKit)框架 : 提供與窗口、按鈕、列表等相關(guān)的類。
  • core Data
Cocoa框架服務(wù)

補(bǔ)充:

內(nèi)核以設(shè)備驅(qū)動(dòng)程序的形式提供與硬件的底層通信。它負(fù)責(zé)管理系統(tǒng)資源,包括調(diào)度要執(zhí)行的程序、管理內(nèi)存和電源,以及執(zhí)行基本的I/O操作。

核心服務(wù)提供的支持比它上面層次更加底層或更加“核心”。例如,這里提供對(duì)集合、網(wǎng)絡(luò)、 調(diào)試、文件管理、文件夾、內(nèi)存管理、線程、時(shí)間和電源的管理。
應(yīng)用程序服務(wù)層包含對(duì)打印和圖形呈現(xiàn)的支持,包括Quartz、OpenGL和Quicktime。

Cocoa層直接位于應(yīng)用程序?qū)又隆U鐖D所示,Cocoa包括Foundation禾口AppKit框架0 Foundation框架提供的類用于處理集合、字符串、內(nèi)存管理、文件系統(tǒng)‘存檔等。AppKit框架提供的類用于管理視圖、窗口、文檔和讓Mac OS X聞名于世的多信息用戶界面。

Cocoa框架用于Mac OS X桌面與筆記本電腦的應(yīng)用程序開發(fā),而Cocoa Touch框架用于 iPhone與ipod Touch的應(yīng)用程序開發(fā)。
Cocoa和Cocoa Touch都有Foundation框架。然而在Cocoa Touch下,UIKit代替了 AppKit框架,以便為很多相同類型的對(duì)象提供支持,比如窗口、視圖、按鈕、文本域等。另外,Cocoa Touch還提供使用加速器(它與GPS和WiFi信號(hào)一樣都能跟綜你的位置)的類和觸摸式界面, 并且去掉了不需要的類,比如支持打印的類。

4.

前文也提到,本文提到的每一個(gè)點(diǎn)都可以單獨(dú)行文,這里只是做一個(gè)淺顯的介紹,后期會(huì)結(jié)合示例代碼做一些更加深入探討。

歡迎指正批評(píng)與交流,本博客將長期更新維護(hù),如果讀完覺得有一定幫助可以點(diǎn)一個(gè)喜歡支持一下~

本文首發(fā)于簡書: http://www.lxweimin.com/p/13580d6d6d2a

未完待續(xù)...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,339評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,713評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評(píng)論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,893評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,201評(píng)論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,397評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,631評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評(píng)論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,128評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,347評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容