百度三面被掛掉之后美浦,沉下心來(lái)總結(jié),構(gòu)建自己的iOS開(kāi)發(fā)體系(上)

在百度三面被掛掉之后项栏,沉下心來(lái)浦辨,整理構(gòu)建自己的開(kāi)發(fā)體系,方便以后查看沼沈。 金三銀四已經(jīng)降臨流酬,為此提供了找了不少學(xué)習(xí)方向給大家,也是一些進(jìn)價(jià)方向列另,希望能幫大家快速提升自己的短板芽腾!

本章節(jié):

標(biāo):不要浪費(fèi)美好的年華拷姿,做自己覺(jué)得對(duì)的事情!

目錄

  • 一旱函、設(shè)計(jì)原則响巢、設(shè)計(jì)模式
  • 二、內(nèi)存管理
  • 三棒妨、多線程
  • 四踪古、Block
  • 五含长、Runtime
  • 六、Runloop
  • 七伏穆、KVO
  • 八拘泞、KVC
  • 九、Category
  • 十枕扫、網(wǎng)絡(luò)
  • 十一陪腌、UI
  • 十二、其他
  • 十三烟瞧、OC對(duì)象相關(guān)
2021年【最新iOS開(kāi)發(fā)面試題】感謝觀看贈(zèng)資料:

下載地址:

全新iOS 電子書(shū)大全 和 iOS 進(jìn)階面試文檔

一诗鸭、設(shè)計(jì)原則、設(shè)計(jì)模式

1参滴、六大設(shè)計(jì)基本原則
定義:一個(gè)類只負(fù)責(zé)一件事
優(yōu)點(diǎn):類的復(fù)雜度降低强岸、可讀性增強(qiáng)、易維護(hù)砾赔、變更引起的風(fēng)險(xiǎn)降低
應(yīng)用:系統(tǒng)提供的UIView和CALayer的關(guān)系:UIView負(fù)責(zé)時(shí)間傳遞蝌箍、事件響應(yīng);CALayer負(fù)責(zé)動(dòng)畫(huà)及展示

定義:對(duì)修改關(guān)閉暴心、對(duì)擴(kuò)展開(kāi)放
- 設(shè)計(jì)的類做好后就不再修改妓盲,如果有新的需求,通過(guò)新加類的方式來(lái)滿足酷勺,而不去修改現(xiàn)有的類的代碼

優(yōu)點(diǎn):靈活本橙、穩(wěn)定(不需修改內(nèi)部代碼,使得被破壞的程度大大下降)
關(guān)鍵:抽象化

使用:
- 我們可以把把行為添加到一個(gè)協(xié)議中脆诉,使用時(shí)遵守這個(gè)協(xié)議即可甚亭。
- 添加類目(Category)方式創(chuàng)建

定義:所有引用父類的地方必須能透明地使用其子類的對(duì)象。
- 通俗點(diǎn)說(shuō)就是击胜,父類可以被子類無(wú)縫替換亏狰,且原有功能不受任何影響

優(yōu)點(diǎn):
- 代碼共享,減少創(chuàng)建類的工作量偶摔,每個(gè)子類都擁有父類的所有屬性和方法
- 提高代碼的可重用性暇唾、擴(kuò)張性,項(xiàng)目的開(kāi)放性

缺點(diǎn):程序的可移植性降低辰斋,增加了對(duì)象間的耦合性

定義:抽象不應(yīng)該依賴于具體實(shí)現(xiàn)策州,具體實(shí)現(xiàn)可以依賴于抽象
核心思想:面向接口編程

優(yōu)點(diǎn):代碼結(jié)構(gòu)清晰,維護(hù)容易
實(shí)例:平時(shí)我們使用 protocol 匿名對(duì)象模式就是依賴倒置原則的最好體現(xiàn)

定義:客戶端不應(yīng)該依賴它不需要的接口

- 使用多個(gè)專門(mén)的協(xié)議宫仗、而不是一個(gè)龐大臃腫的協(xié)議够挂。
- 協(xié)議中的方法應(yīng)當(dāng)盡量少

例:UITableViewDataSource、UITableViewDelegate
優(yōu)點(diǎn):解耦藕夫、增強(qiáng)可讀性孽糖、可擴(kuò)展性枯冈、可維護(hù)性

定義:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有盡可能少的了解办悟。
- 也就是說(shuō)尘奏,如果兩個(gè)類不必彼此直接通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用病蛉。

迪米特法則應(yīng)用:
- 外觀模式(Facade)
- 中介者模式(Mediator)
- 匿名對(duì)象

優(yōu)點(diǎn):使對(duì)象之間的耦合降到最底炫加,從而使得類具有很好的可讀性和可維護(hù)性。

特點(diǎn)總結(jié)

  • 單一職責(zé)原則主要說(shuō)明:類的職責(zé)要單一
  • 里氏替換原則強(qiáng)調(diào):不要破壞繼承體系
  • 依賴倒置原則描述要:面向接口編程
  • 接口隔離原則講解:設(shè)計(jì)接口的時(shí)候要精簡(jiǎn)
  • 迪米特法則告訴我們:要降低耦合
  • 開(kāi)閉原則講述的是:對(duì)擴(kuò)展開(kāi)放铡恕,對(duì)修改關(guān)閉

  • 設(shè)計(jì)模式
TODO(待填充);??????????

二琢感、內(nèi)存管理

規(guī)則

  • 在iOS中,使用 “引用計(jì)數(shù)” 來(lái)管理OC對(duì)象的內(nèi)存
  • 新創(chuàng)建的OC對(duì)象探熔,引用計(jì)數(shù)是1驹针;
  • 調(diào)用retain會(huì)讓OC對(duì)象的引用計(jì)數(shù)+1,調(diào)用release會(huì)讓OC對(duì)象的引用計(jì)數(shù)-1
  • 當(dāng)引用計(jì)數(shù)減為0诀艰,OC對(duì)象就會(huì)銷毀柬甥,釋放占用的內(nèi)存空間
  • 當(dāng)調(diào)用 alloc、new其垄、copy苛蒲、mutableCopy 方法返回了一個(gè)對(duì)象,在不需要這個(gè)對(duì)象時(shí)绿满,要調(diào)用release或者aoturelease釋放
2臂外、引用計(jì)數(shù)怎么存儲(chǔ)?
- 可以直接存儲(chǔ)在isa指針中
- 如果不夠存儲(chǔ)的話喇颁,會(huì)存儲(chǔ)在SideTable結(jié)構(gòu)體的refcnts散列表中

struct SideTable {
    spinlock_t stock;
    RefcountMap refcnts; // 存放著對(duì)象引用計(jì)數(shù)的散列表
    weak_table_t weak_table;
}

3漏健、ARC具體為引用計(jì)數(shù)做了哪些工作?
- 編譯階段自動(dòng)添加代碼

ARC是LLVM編譯器和Runtime系統(tǒng)相互協(xié)作的一個(gè)結(jié)果
- 編譯器幫我們實(shí)現(xiàn)內(nèi)存管理相關(guān)的代碼
- Runtime在程序運(yùn)行過(guò)程中處理弱引用

4橘霎、深拷貝與淺拷貝
概念:
- 深拷貝:內(nèi)容拷貝蔫浆,產(chǎn)生新的對(duì)象
- 淺拷貝:指針拷貝,沒(méi)有產(chǎn)生新的對(duì)象姐叁,原對(duì)象的引用計(jì)數(shù)+1
- 完全拷貝:深拷貝的一種瓦盛,能拷貝多層內(nèi)容(使用歸解檔技術(shù))

執(zhí)行結(jié)果:
- copy:不可變拷貝,產(chǎn)生不可變副本
- mutableCopy:可變拷貝外潜,產(chǎn)生可變副本

準(zhǔn)則:不可變對(duì)象的copy方法是淺拷貝原环,其余都是深拷貝??????????
原因:
- 它是不可變對(duì)象,沒(méi)有必要拷貝一份出來(lái)处窥,指向同一塊地址還節(jié)省內(nèi)存
- 不可變對(duì)象調(diào)用copy返回他本身嘱吗,不可變對(duì)象copy就相當(dāng)于是retain

1、對(duì)象的拷貝
- 遵守協(xié)議(<NSCopying, NSMutableCopying>)
- 實(shí)現(xiàn)協(xié)議方法

- (id)copyWithZone:(NSZone *)zone {
    Person *person = [Person allocWithZone:zone];
    person.name = self.name;
    return person;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
    Person *person = [Person allocWithZone:zone];
    person.name = self.name;
    return person;
}

2碧库、集合對(duì)象的拷貝
- 對(duì)于集合類的可變對(duì)象來(lái)說(shuō)柜与,深拷貝并非嚴(yán)格意義上的深復(fù)制,只能算是單層深復(fù)制
- 即雖然新開(kāi)辟了內(nèi)存地址嵌灰,但是存放在內(nèi)存上的值(也就是數(shù)組里的元素仍然之鄉(xiāng)員數(shù)組元素值弄匕,并沒(méi)有另外復(fù)制一份),這就叫做單層深復(fù)制
- 對(duì)于集合類的對(duì)象如何實(shí)現(xiàn)每一層都深拷貝呢沽瞭?(1迁匠、initWithArray:copyItems、2驹溃、歸檔解檔技術(shù))

#import <Foundation/Foundation.h>

@interface Person : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;

@end

#import "Person.h"

@implementation Person

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self.name = [aDecoder decodeObjectForKey:@"name"];
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
}

@end

歸檔和解檔的概念補(bǔ)充:
有時(shí)存在這樣的需求城丧,即將程序中使用的多個(gè)對(duì)象及其屬性值,以及它們的相互關(guān)系保存到文件中豌鹤,或者發(fā)送給另外的進(jìn)程亡哄。為了實(shí)現(xiàn)此功能,foundation框架中布疙,可以把相互關(guān)聯(lián)的多個(gè)對(duì)象歸檔為二進(jìn)制文件蚊惯,而且還能將對(duì)象的關(guān)系從二進(jìn)制文件中還原出來(lái)。

5灵临、weak指針實(shí)現(xiàn)原理截型,SideTable的結(jié)構(gòu)是什么樣?
1儒溉、常用知識(shí)點(diǎn):
- 所引用對(duì)象的計(jì)數(shù)器不會(huì)+1宦焦,并在引用對(duì)象被釋放的時(shí)候自動(dòng)被設(shè)置為nil
- 通常用于解決循環(huán)引用問(wèn)題

2、weak指針實(shí)現(xiàn)原理
- Runtime維護(hù)了一個(gè)weak表顿涣,用于存儲(chǔ)指向某個(gè)對(duì)象的所有weak指針波闹。
- weak表其實(shí)就是一個(gè)哈希表,key:對(duì)象的內(nèi)存地址园骆;value:指向該對(duì)象的所有弱引用的指針
- 當(dāng)對(duì)象銷毀的時(shí)候舔痪,通過(guò)對(duì)象的地址值,取出對(duì)象的弱引用表锌唾,將表里面的弱引用清除

3锄码、為什么弱引用不會(huì)導(dǎo)致循環(huán)引用?
- 沒(méi)有增加引用計(jì)數(shù)

4晌涕、SideTable的結(jié)構(gòu)是什么樣的?
struct SideTable {
    // 保證原子操作的自旋鎖
    spinlock_t slock;
    // 引用計(jì)數(shù)的 hash 表
    RefcountMap refcnts;
    // weak 引用全局 hash 表
    weak_table_t weak_table;
};

5滋捶、weak屬性如何自動(dòng)置nil的? 具體到如何查找的余黎?
TODO(待填充);??????????

6重窟、自動(dòng)釋放池相關(guān)
1、以下代碼輸出什么惧财?會(huì)有什么問(wèn)題巡扇?

for (int i = 0; i < 1000000; i ++) {
    NSString *string = @"Abc";
    string = [string lowercaseString];
    // string = [string stringByAppendingString:@"xyz"];
    string = [string stringByAppendingFormat:@"xyz"];
    NSLog(@"%d-%@", i, string);
}

問(wèn)題解析:
- 每執(zhí)行一次循環(huán)扭仁,就會(huì)有一個(gè)string加到當(dāng)前NSRunloop中的自動(dòng)釋放池中
- 只有當(dāng)自動(dòng)釋放池被release的時(shí)候,自動(dòng)釋放池中的標(biāo)示了autorelease的這些數(shù)據(jù)所占用的內(nèi)存空間才能被釋放掉
- 當(dāng)someLargeNumber大到一定程度時(shí)厅翔,內(nèi)存空間將被耗盡而沒(méi)有被釋放掉乖坠,所以就出現(xiàn)了內(nèi)存溢出的現(xiàn)象。

解決方案:在循環(huán)里面加個(gè)自動(dòng)釋放池
for (int i = 0; i < 1000000; i ++) {
    @autoreleasepool {
        NSString *string = @"Abc";
        string = [string lowercaseString];
        string = [string stringByAppendingFormat:@"xyz"];
        NSLog(@"%d-%@", i, string);
    }
}

2刀闷、自動(dòng)釋放池底層結(jié)構(gòu):
- AutoreleasPool是通過(guò)以AutoreleasePoolPage為結(jié)點(diǎn)的 “雙向鏈表” 來(lái)實(shí)現(xiàn)的

3熊泵、AutoreleasPool運(yùn)行的三個(gè)過(guò)程:
- objc_autoreleasePoolPush()
- [objc autorelease] 
- objc_autoreleasePoolPop(void *)

objc_autoreleasePoolPush()
- 調(diào)用的AutoreleasePoolPage的push函數(shù)
- 一個(gè)push操作其實(shí)就是創(chuàng)建一個(gè)新的Autoreleasepool
- 對(duì)應(yīng)AutoreleasePoolPage的具體實(shí)現(xiàn)就是往AutoreleasePoolPage中的next位置插入一個(gè) POOL_SENTINEL
- 并且返回插入的 POOL_SENTINEL 的內(nèi)存地址。這個(gè)地址也就是我們前面提到的 pool token
- 在執(zhí)行 pop 操作的時(shí)候作為函數(shù)的入?yún)?
push 函數(shù)通過(guò)調(diào)用 autoreleaseFast 函數(shù)來(lái)執(zhí)行具體的插入操作
autoreleaseFast 函數(shù)在執(zhí)行具體的插入操作時(shí)三種情況不同的處理
- 當(dāng)前 page 存在且沒(méi)有滿時(shí)甸昏,直接將對(duì)象添加到當(dāng)前 page 中顽分,即 next 指向的位置;
- 當(dāng)前 page 存在且已滿時(shí)施蜜,創(chuàng)建一個(gè)新的 page 卒蘸,并將對(duì)象添加到新創(chuàng)建的 page 中;
- 當(dāng)前 page 不存在時(shí)翻默,即還沒(méi)有 page 時(shí)悬秉,創(chuàng)建第一個(gè) page ,并將對(duì)象添加到新創(chuàng)建的 page 中

objc_autoreleasePoolPop(void *) 函數(shù)本質(zhì)
- 就是是調(diào)用的 AutoreleasePoolPage 的 pop 函數(shù)
- pop 函數(shù)的入?yún)⒕褪?push 函數(shù)的返回值冰蘑,也就是 POOL_SENTINEL 的內(nèi)存地址和泌,即 pool token 。
- 當(dāng)執(zhí)行 pop 操作時(shí)祠肥,內(nèi)存地址在 pool token 之后的所有 autoreleased 對(duì)象都會(huì)被 release 武氓。
- 直到 pool token 所在 page 的 next 指向 pool token 為止。

TODO(待填充);??????????
4仇箱、autoreleasepool和線程的關(guān)系县恕?

7、Copy剂桥、Strong忠烛、Weak、Assign的區(qū)別权逗?
assign
- 用于對(duì)基本數(shù)據(jù)類型進(jìn)行賦值操作美尸,不更改引用計(jì)數(shù)
- 也可以用來(lái)修飾對(duì)象,但是被assign修飾的對(duì)象在釋放后斟薇,指針的地址還是存在的师坎,指針并沒(méi)有被置為nil,成為野指針
- 之所以可以修飾基本數(shù)據(jù)類型堪滨,因?yàn)榛緮?shù)據(jù)類型一般分配在棧上胯陋,棧的內(nèi)存會(huì)由系統(tǒng)自動(dòng)處理,不會(huì)造成野指針。

weak:
- 修飾Object類型遏乔,修飾的對(duì)象在釋放后义矛,指針地址會(huì)被置為nil,是一種弱引用
- 在ARC環(huán)境下盟萨,為避免循環(huán)引用症革,往往會(huì)把delegate屬性用weak修飾
- weak和strong不同的是:當(dāng)一個(gè)對(duì)象不再有strong類型的指針指向它的時(shí)候,它就會(huì)被釋放鸯旁,即使還有weak型指針指向它,那么這些weak型指針也將被清除量蕊。

strong:
- ARC下的strong等同于MRC下的retain都會(huì)把對(duì)象引用計(jì)數(shù)加1

copy:
- 會(huì)在內(nèi)存里拷貝一份對(duì)象铺罢,兩個(gè)指針指向不同的內(nèi)存地址。
- 一般用來(lái)修飾NSString等有對(duì)應(yīng)可變類型的對(duì)象残炮,因?yàn)樗麄冇锌赡芎蛯?duì)應(yīng)的可變類型(NSMutableString)之間進(jìn)行賦值操作韭赘,為確保可變對(duì)象變化時(shí)势就,對(duì)象中的字符串不被修改 泉瞻,應(yīng)該在設(shè)置屬性時(shí)拷貝一份。
- 而若用strong修飾苞冯,如果可變對(duì)象變化袖牙,對(duì)象中的字符串屬性也會(huì)跟著變化。

1舅锄、block屬性為什么需要用copy來(lái)修飾鞭达?
- 因?yàn)樵贛RC下,block在創(chuàng)建的時(shí)候皇忿,它的內(nèi)存是分配在棧(stack)上的畴蹭,而不是在堆(heap)上,可能被隨時(shí)回收鳍烁。
- 他本身的作于域是屬于創(chuàng)建時(shí)候的作用域叨襟,一旦在創(chuàng)建時(shí)候的作用域外面調(diào)用block將導(dǎo)致程序崩潰。
- 通過(guò)copy可以把block拷貝(copy)到堆幔荒,保證block的聲明域外使用糊闽。
- 在ARC下寫(xiě)不寫(xiě)都行,編譯器會(huì)自動(dòng)對(duì)block進(jìn)行copy操作爹梁。

2墓怀、代理為什么使用weak修飾?
- weak指明該對(duì)象并不負(fù)責(zé)保持delegate這個(gè)對(duì)象卫键,delegate的銷毀由外部控制
- 如果用strong修飾傀履,強(qiáng)引用后外界不能銷毀delegate對(duì)象,會(huì)導(dǎo)致循環(huán)引用

3、為什么NSMutableArray一般不用copy修飾钓账?
- (void)setData:(NSMutableArray *)data {
    if (_data != data) {
        [_data release];
        _data = [data copy];
    }
}
拷貝完成后:可變數(shù)組->不可變數(shù)組碴犬,在外操作時(shí)(添加、刪除等)會(huì)存在問(wèn)題

4梆暮、說(shuō)到野指針了服协,什么是“僵尸對(duì)象”?
#[iOS-野指針與僵尸對(duì)象](https://www.cnblogs.com/junhuawang/p/9213093.html)?????

- 一個(gè)OC對(duì)象引用計(jì)數(shù)為0被釋放后就變成僵尸對(duì)象啦粹,僵尸對(duì)象的內(nèi)存已經(jīng)被系統(tǒng)回收
- 雖然可能該對(duì)象還存在偿荷,數(shù)據(jù)依然在內(nèi)存中,但僵尸對(duì)象已經(jīng)是不穩(wěn)定對(duì)象了唠椭,不可以再訪問(wèn)或者使用
- 它的內(nèi)存是隨時(shí)可能被別的對(duì)象申請(qǐng)而占用的

8跳纳、- (void)dealloc底層執(zhí)行了什么?
- (void)dealloc {
    _objc_rootDealloc(self);
}

void _objc_rootDealloc(id obj) {
    ASSERT(obj);
    obj->rootDealloc();
}

inline void objc_object::rootDealloc() {
    if (isTaggedPointer()) return;  // fixme necessary?

    if (fastpath(isa.nonpointer  &&          // 無(wú)優(yōu)化過(guò)isa指針
                 !isa.weakly_referenced  &&  // 無(wú)弱引用
                 !isa.has_assoc  &&          // 無(wú)關(guān)聯(lián)對(duì)象
                 !isa.has_cxx_dtor  &&       // 無(wú)cxx析構(gòu)函數(shù)
                 !isa.has_sidetable_rc)) {   // 不存在引用計(jì)數(shù)器是否過(guò)大無(wú)法存儲(chǔ)在isa中(使用 sidetable 來(lái)存儲(chǔ)引用計(jì)數(shù))
        // 直接釋放
        assert(!sidetable_present());
        free(this);
    } else {
        // 下一步
        object_dispose((id)this);
    }
}

// 如果不能快速釋放寺庄,則調(diào)用 object_dispose()方法,做下一步的處理
static id _object_dispose(id anObject) {
    if (anObject==nil) return nil;

    objc_destructInstance(anObject);

    anObject->initIsa(_objc_getFreedObjectClass ());

    free(anObject);
    return nil;
}

void *objc_destructInstance(id obj) {
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();               // 是否存在析構(gòu)函數(shù)
        bool assoc = obj->hasAssociatedObjects();   // 是否有關(guān)聯(lián)對(duì)象

        // This order is important.
        if (cxx) object_cxxDestruct(obj);           // 銷毀成員變量
        if (assoc) _object_remove_assocations(obj); // 釋放動(dòng)態(tài)綁定的對(duì)象
        obj->clearDeallocating();
    }
    return obj;
}

/*
 * clearDeallocating一共做了兩件事
 *
 * 1力崇、將對(duì)象弱引用表清空斗塘,即將弱引用該對(duì)象的指針置為nil
 * 2、清空引用計(jì)數(shù)表
 * - 當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)值過(guò)大(超過(guò)255)時(shí)亮靴,引用計(jì)數(shù)會(huì)存儲(chǔ)在一個(gè)叫 SideTable 的屬性中
 * - 此時(shí)isa的 has_sidetable_rc 值為1馍盟,這就是為什么弱引用不會(huì)導(dǎo)致循環(huán)引用的原因
 */
inline void  objc_object::clearDeallocating() {
    if (slowpath(!isa.nonpointer)) {
        // Slow path for raw pointer isa.
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
        // Slow path for non-pointer isa with weak refs and/or side table data.
        clearDeallocating_slow();
    }
    assert(!sidetable_present());
}


三、多線程

9茧吊、多線程 - GCD相關(guān)
GCD核心概念:「任務(wù)」朽合、「隊(duì)列」

1、任務(wù):
- 概念:指操作饱狂,線程中執(zhí)行的那段代碼曹步,GCD主要放在block中;
- 執(zhí)行任務(wù)的方式:「同步執(zhí)行」休讳、「異步執(zhí)行」讲婚;
- 區(qū)別:是否等待隊(duì)列的任務(wù)執(zhí)行結(jié)束,是否具備開(kāi)啟新縣城的能力俊柔;

同步執(zhí)行(sync)
- 同步添加任務(wù)到指定隊(duì)列中筹麸,在添加的任務(wù)執(zhí)行結(jié)束之前,會(huì)一直等待雏婶,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行
- 只能在當(dāng)前線程中執(zhí)行任務(wù)物赶,不具備開(kāi)啟新線程的能力

異步執(zhí)行(async)
- 異步添加任務(wù)到指定隊(duì)列中,不會(huì)做任何等待留晚,可以繼續(xù)執(zhí)行任務(wù)
- 可以在新的線程中執(zhí)行任務(wù)酵紫,具備開(kāi)啟新縣城的能力
- ??異步執(zhí)行雖然具有開(kāi)啟新線程的能力,但不一定開(kāi)啟新線程。(與任務(wù)指定的隊(duì)列類型有關(guān))

2奖地、隊(duì)列(Dispatch Queue)
- 概念:執(zhí)行任務(wù)的等待隊(duì)列橄唬,即用來(lái)存放任務(wù)的隊(duì)列
- 結(jié)構(gòu):特殊的線性表,采用FIFO(先進(jìn)先出)原則参歹。即每讀取一個(gè)任務(wù)仰楚,則從隊(duì)列中釋放一個(gè)任務(wù)

串行隊(duì)列:(Serial Dispatch Queue)
- 每次只有一個(gè)任務(wù)被執(zhí)行,任務(wù)依次執(zhí)行(只開(kāi)啟一個(gè)線程犬庇,一個(gè)任務(wù)執(zhí)行完成后僧界,再執(zhí)行下一個(gè)任務(wù))

并發(fā)隊(duì)列:(Concurrent Dispatch Queue)
- 可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行。(可以開(kāi)啟多個(gè)線程臭挽,并且同時(shí)執(zhí)行任務(wù))
- ??并發(fā)隊(duì)列的「并發(fā)」功能只有在異步(dispatch_async)方法下才有效

3捂襟、GCD使用步驟
- 創(chuàng)建一個(gè)隊(duì)列(串行隊(duì)列/并發(fā)隊(duì)列)
- 將任務(wù)追加到任務(wù)的等待隊(duì)列中,然后系統(tǒng)就會(huì)根據(jù)任務(wù)類型執(zhí)行任務(wù)(同步執(zhí)行/異步執(zhí)行)

4埋哟、死鎖條件:
- 使用sync函數(shù)往當(dāng)前串行隊(duì)列中添加任務(wù),會(huì)卡住當(dāng)前的串行隊(duì)列郎汪。

面試題一赤赊、打印順序
NSLog(@"執(zhí)行任務(wù)1");
dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("com.example.gcd.2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    NSLog(@"執(zhí)行任務(wù)2");
    dispatch_sync(queue2, ^{
        NSLog(@"執(zhí)行任務(wù)3");
    });
    NSLog(@"執(zhí)行任務(wù)4");
});
NSLog(@"執(zhí)行任務(wù)5");

2021-03-01 16:47:46.122744+0800 ZF_Beta[17625:344152] 執(zhí)行任務(wù)1
2021-03-01 16:47:46.122977+0800 ZF_Beta[17625:344152] 執(zhí)行任務(wù)5
2021-03-01 16:47:46.122984+0800 ZF_Beta[17625:344229] 執(zhí)行任務(wù)2
2021-03-01 16:47:46.123171+0800 ZF_Beta[17625:344229] 執(zhí)行任務(wù)3
2021-03-01 16:47:46.123300+0800 ZF_Beta[17625:344229] 執(zhí)行任務(wù)4

dispatch_queue_t ser = dispatch_queue_create("ser", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
dispatch_async(ser, ^{
    NSLog(@"2");
});
NSLog(@"3");
dispatch_sync(ser, ^{
    NSLog(@"4");
});
NSLog(@"5");

2021-02-26 11:25:15.703849+0800 ZF_Beta[6156:123418] 1
2021-02-26 11:25:15.704053+0800 ZF_Beta[6156:123418] 3
2021-02-26 11:25:15.704062+0800 ZF_Beta[6156:123698] 2
2021-02-26 11:25:15.704231+0800 ZF_Beta[6156:123418] 4
2021-02-26 11:25:15.704311+0800 ZF_Beta[6156:123418] 5

- (void)viewDidLoad {
   [self performSelector:@selector(test3) withObject:nil afterDelay:0];
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"---111");
    });
    NSLog(@"---333");
}

- (void)test3 {
    NSLog(@"---222");
}

---333
---111
---222

- (void)viewDidLoad {
    [self performSelector:@selector(test1) withObject:nil afterDelay:0];
    [self performSelector:@selector(test2) withObject:nil];
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"===3");
    });
    [UIView animateWithDuration:10 animations:^{
        NSLog(@"===4");
    }];
}

- (void)test1 {
    NSLog(@"===1");
}

- (void)test2 {
    NSLog(@"===2");
}

2021-03-04 17:41:03.759310+0800 property[25604:424718] ===2
2021-03-04 17:41:03.759642+0800 property[25604:424718] ===4
2021-03-04 17:41:03.788454+0800 property[25604:424718] ===3
2021-03-04 17:41:03.789335+0800 property[25604:424718] ===1

面試題二、如何打造線程安全的NSMutableArray煞赢?
- 線程鎖:使用線程鎖在對(duì)數(shù)組讀寫(xiě)時(shí)候加鎖
- 派發(fā)隊(duì)列:
《Effective Objective 2.0》中41條提出的觀點(diǎn)抛计,串行同步:將讀取和寫(xiě)入都安排在同一個(gè)隊(duì)列里,可保證數(shù)據(jù)同步照筑。

面試題三吹截、如何異步下載多張小圖最后合成一張大圖?
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片3 */ }); 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 合并圖片
});

面試題四凝危、什么是線程安全波俄?
- 多線程操作過(guò)程中往往都是多個(gè)線程并發(fā)執(zhí)行的,因此同一個(gè)資源可能被多個(gè)線程同時(shí)訪問(wèn)蛾默,造成資源搶奪懦铺。
- 線程安全就是多條線程同時(shí)訪問(wèn)一段代碼,不會(huì)造成數(shù)據(jù)混亂的情況

面試題五支鸡、如何設(shè)置常駐線程冬念?

面試題六、在異步線程發(fā)送通知牧挣,在主線程接收通知急前。會(huì)不會(huì)有什么問(wèn)題?

面試題七瀑构、GCD線程是如何調(diào)度的

面試題八裆针、如何實(shí)現(xiàn)多個(gè)任務(wù)執(zhí)行完后,再統(tǒng)一處理?
- 同步阻塞
- 柵欄函數(shù)
- 線程組

??基于runloop的線程本菘椋活码邻、銷毀與通信:http://www.reibang.com/p/4d5b6fc33519

下一章:百度三面被掛掉之后,沉下心來(lái)總結(jié)另假,構(gòu)建自己的iOS開(kāi)發(fā)體系(下)

小編文章請(qǐng)觀看合集

文章來(lái)源作者:強(qiáng)子ly

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市戈轿,隨后出現(xiàn)的幾起案子凌受,更是在濱河造成了極大的恐慌,老刑警劉巖思杯,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胜蛉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡色乾,警方通過(guò)查閱死者的電腦和手機(jī)誊册,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)暖璧,“玉大人案怯,你說(shuō)我怎么就攤上這事∨彀欤” “怎么了嘲碱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)局蚀。 經(jīng)常有香客問(wèn)我麦锯,道長(zhǎng),這世上最難降的妖魔是什么琅绅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任离咐,我火速辦了婚禮,結(jié)果婚禮上奉件,老公的妹妹穿的比我還像新娘宵蛀。我一直安慰自己,他們只是感情好县貌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布术陶。 她就那樣靜靜地躺著,像睡著了一般煤痕。 火紅的嫁衣襯著肌膚如雪梧宫。 梳的紋絲不亂的頭發(fā)上接谨,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音塘匣,去河邊找鬼脓豪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忌卤,可吹牛的內(nèi)容都是我干的扫夜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼驰徊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼笤闯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起棍厂,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颗味,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后牺弹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浦马,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年张漂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晶默。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鹃锈,死狀恐怖荤胁,靈堂內(nèi)的尸體忽然破棺而出瞧预,到底是詐尸還是另有隱情屎债,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布垢油,位于F島的核電站盆驹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏滩愁。R本人自食惡果不足惜躯喇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硝枉。 院中可真熱鬧廉丽,春花似錦、人聲如沸妻味。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)责球。三九已至焦履,卻和暖如春拓劝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉裤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工郑临, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屑宠。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓厢洞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親侨把。 傳聞我的和親對(duì)象是個(gè)殘疾皇子犀变,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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