iOS面試題總結(jié)(一)

把網(wǎng)上的一些結(jié)合自己面試時(shí)遇到的面試題總結(jié)了一下,以后有新的還會(huì)再加進(jìn)來(lái)妙痹。

1. OC 的理解與特性

OC 作為一門面向?qū)ο蟮恼Z(yǔ)言,自然具有面向?qū)ο蟮恼Z(yǔ)言特性鼻疮,如封裝怯伊、繼承、多態(tài)判沟。它具有靜態(tài)語(yǔ)言的特性又有動(dòng)態(tài)語(yǔ)言的效率耿芹。它的動(dòng)態(tài)特性表現(xiàn)在三個(gè)地方:動(dòng)態(tài)類型、動(dòng)態(tài)綁定和動(dòng)態(tài)加載水评。之所以叫做動(dòng)態(tài)猩系,是因?yàn)楸仨毜竭\(yùn)行時(shí)才會(huì)做一些事情。

動(dòng)態(tài)類型:即運(yùn)行時(shí)再?zèng)Q定對(duì)象的類型中燥,比如 id 類型寇甸;

動(dòng)態(tài)綁定:基于動(dòng)態(tài)類型,在某個(gè)實(shí)例對(duì)象被確定后疗涉,其類型便被確定了拿霉,該對(duì)象對(duì)應(yīng)的屬性和響應(yīng)的消息也被完全確定。

動(dòng)態(tài)加載:根據(jù)需求加載所需要的資源咱扣,比如根據(jù)不同的機(jī)型做適配绽淘。

2. 簡(jiǎn)述對(duì)內(nèi)存管理的理解

OC 通過(guò)引用計(jì)數(shù)來(lái)對(duì)內(nèi)存進(jìn)行管理,核心思想是遵循 “誰(shuí)創(chuàng)建闹伪,誰(shuí)釋放沪铭,誰(shuí)引用,誰(shuí)管理” 的機(jī)制偏瓤,分為兩種方式:MRC 和 ARC 杀怠。MRC 是 當(dāng)創(chuàng)建或引用一個(gè)對(duì)象的時(shí)候,需要向它發(fā)送 alloc厅克、copy赔退、retain 消息,當(dāng)釋放該對(duì)象時(shí)需要發(fā)送 release 消息证舟,當(dāng)該對(duì)象的引用計(jì)數(shù)為 0 時(shí)硕旗,系統(tǒng)將釋放該對(duì)象。ARC 是由系統(tǒng)在適當(dāng)?shù)奈恢貌迦?release 或 autorelease女责,它引用了 strong 和 weak 關(guān)鍵字漆枚,用 strong 修飾的指針變量指向?qū)ο髸r(shí),當(dāng)指針指向新值或指針不再存在時(shí)相關(guān)聯(lián)的對(duì)象就會(huì)自動(dòng)釋放抵知,而用 weak 修飾的指針指向?qū)ο髸r(shí)墙基,當(dāng)對(duì)象的擁有者指向新值或不存在時(shí)昔榴,指針會(huì)置為 nil。

3. 如何理解 MVC 模式

MVC 是一種架構(gòu)模式碘橘。M 表示數(shù)據(jù)模型 model互订,V 表示視圖 VIew,C 表示控制器 Controller痘拆。

Model 負(fù)責(zé)存儲(chǔ)仰禽、定義、操作數(shù)據(jù)纺蛆;

View 用來(lái)展示數(shù)據(jù)給用戶吐葵,和用戶進(jìn)行操作交互;

Controller 是 Model 和 View 的協(xié)調(diào)者桥氏,Controller 把 Model 里的數(shù)據(jù)拿過(guò)來(lái)給 View 用温峭。Controller 可以直接與 Model 和 View 進(jìn)行通信,而 View 不能和 Controller 直接通信需要代理協(xié)議的方式字支,當(dāng)有數(shù)據(jù)更新時(shí)凤藏,Model 也要與 Controller 進(jìn)行通信,比如使用 notification 和 KVO 堕伪。Model 和 View 不能直接通信揖庄,因?yàn)檫@樣就違背了 MVC 的設(shè)計(jì)思想。

4. 定時(shí)器和線程的區(qū)別

定時(shí)器:可以執(zhí)行多次欠雌,默認(rèn)在主線程中蹄梢;

線程:只能執(zhí)行一次

5. NSNotification、Block富俄、Delegate 和 KVO 的區(qū)別

代理是一種回調(diào)機(jī)制禁炒,且是一對(duì)一的關(guān)系,而通知可以一對(duì)多霍比,代理效率比通知高幕袱;

KVO 是被觀察者向觀察者直接發(fā)送通知,而通知相反桂塞;

代理需要定義協(xié)議方法凹蜂,代理對(duì)象實(shí)現(xiàn)協(xié)議方法馍驯,并且需要建立代理關(guān)系才能實(shí)現(xiàn)通信阁危,而 Block 更加簡(jiǎn)潔,不需要定義繁瑣的協(xié)議方法汰瘫,但若通信事件比較多的話狂打,建議用代理,而通知主要用于一對(duì)多情況下通信混弥,通信對(duì)象之間不需要建立關(guān)系趴乡。

6. TCP 和 UDP 的區(qū)別

TCP 為傳輸控制層協(xié)議对省。這種協(xié)議提供面向連接的、可靠的晾捏、點(diǎn)到點(diǎn)的通信蒿涎;

UDP 為用戶數(shù)據(jù)報(bào)協(xié)議。這種協(xié)議提供非連接的惦辛、不可靠的劳秋、點(diǎn)到多的通信但是比 TCP 快。

7. TCP 的三次握手

第一次握手:客戶端發(fā)送 syn 包(syn=j)到服務(wù)器胖齐,并進(jìn)入 SYN_SEND 狀態(tài) 玻淑,等待服務(wù)器確認(rèn)茵臭;

第二次握手:服務(wù)器收到 syn 包梳侨,必須確認(rèn)客戶的 SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè) syn 包(syn=k)太伊,即 SYN+ACK 包剿另,此時(shí)服務(wù)器進(jìn)入 SYN+RECV 狀態(tài)箫锤;

第三次握手:客戶端收到服務(wù)器的 SYN+ACK 包,向服務(wù)器發(fā)送確認(rèn)包 ACK(ack=k+1)雨女,此時(shí)發(fā)送完畢麻汰,客戶端和服務(wù)端進(jìn)入 ESTABLISHED 狀態(tài),完成三次握手

8. 對(duì)沙盒的理解戚篙,App Bundle 里面都有什么

每個(gè) iOS 應(yīng)用都被限制在 “沙盒” 中五鲫,“沙盒” 相當(dāng)于一個(gè)加了僅主人可見(jiàn)權(quán)限的文件夾,就是應(yīng)用程序在安裝過(guò)程中岔擂,系統(tǒng)為每個(gè)單獨(dú)的應(yīng)用程序生成它的主目錄和一些關(guān)鍵的子目錄位喂。

蘋果對(duì)沙盒有以下幾條限制:

1. 應(yīng)用程序可以在自己的沙盒里運(yùn)作,但不能訪問(wèn)任何其他應(yīng)用程序的沙盒乱灵;

2.應(yīng)用程序間不能共享數(shù)據(jù)塑崖,沙盒里的文件不能被復(fù)制到其他應(yīng)用程序文件夾中,也不能把其他應(yīng)用程序文件夾中的文件復(fù)制到沙盒里痛倚;

3.蘋果禁止任何讀规婆、寫沙盒以外的文件,禁止應(yīng)用程序?qū)?nèi)容寫到沙盒以外的文件夾中蝉稳;

沙盒根目錄里有三個(gè)文件夾和一個(gè) .app 包:

AppName.app 目錄:這是應(yīng)用程序的程序包目錄抒蚜,包含應(yīng)用程序的本身。由于應(yīng)用程序必須經(jīng)過(guò)簽名耘戚,所以您在運(yùn)行時(shí)不能對(duì)這個(gè)目錄中的內(nèi)容進(jìn)行修改嗡髓,否則可能會(huì)使應(yīng)用程序無(wú)法啟動(dòng)。

Documents:iTunes會(huì)備份該目錄收津。一般用來(lái)存儲(chǔ)需要持久化的數(shù)據(jù)饿这,這里不能存緩存文件,否則上架不被通過(guò)浊伙;

Library:下有兩個(gè)文件夾,Library/Caches:緩存长捧,iTunes不會(huì)備份該目錄嚣鄙。內(nèi)存不足時(shí)會(huì)被清除,應(yīng)用沒(méi)有運(yùn)行時(shí)串结,可能會(huì)被清除拗慨,SDWebImage緩存路徑就是這個(gè)。一般存儲(chǔ)體積大奉芦、不需要備份的非重要數(shù)據(jù)赵抢;Library/Preference:iTunes同會(huì)備份該目錄,可以用來(lái)存儲(chǔ)一些偏好設(shè)置

Temp:iTunes不會(huì)備份這個(gè)目錄声功,用來(lái)保存臨時(shí)數(shù)據(jù)烦却,應(yīng)用退出時(shí)會(huì)清除該目錄下的數(shù)據(jù)。

App Bundle 里面包括:

Info.plist:此文件包含了應(yīng)用程序的配置信息.系統(tǒng)依賴此文件以獲取應(yīng)用程序的相關(guān)信息

可執(zhí)行文件:此文件包含應(yīng)用程序的入口和通過(guò)靜態(tài)連接到應(yīng)用程序target的代碼

資源文件:圖片,聲音文件一類的

其他:可以嵌入定制的數(shù)據(jù)資源

9. 為什么 OC 中的分類先巴、擴(kuò)展和協(xié)議是重要的

因?yàn)樗鼈冊(cè)试S以不創(chuàng)建子類的方式復(fù)用代碼其爵,這意味著與其他只能通過(guò)子類化來(lái)共享代碼的語(yǔ)言相比,在 OC 中伸蚯。類層次結(jié)構(gòu)可能更加扁平摩渺。

10. 為什么封裝是重要的

封裝使得維護(hù)工作變得更加容易,方便復(fù)用剂邮,降低耦合

11. 為什么訪問(wèn)器是重要的

通過(guò)訪問(wèn)器可以在不直接訪問(wèn)實(shí)例變量的情況下設(shè)置和獲取實(shí)例變量的值

12. 靜態(tài)類型和 id 類型的區(qū)別

使用 id 之后變量的類型是在運(yùn)行時(shí)確定的摇幻,對(duì)象所屬的類將確定哪些方法可用,但這會(huì)稍微增加一些運(yùn)行時(shí)開銷挥萌。靜態(tài)類型則不會(huì)增加運(yùn)行時(shí)開銷绰姻,它允許編譯器而非運(yùn)行時(shí)代碼進(jìn)行錯(cuò)誤檢測(cè)。

13. 垃圾收集和引用計(jì)數(shù)的區(qū)別

垃圾收集是在運(yùn)行時(shí)的一個(gè)過(guò)程引瀑,引用計(jì)數(shù)是在編寫代碼和編譯代碼的時(shí)候?qū)崿F(xiàn)的狂芋,但其作用需要在運(yùn)行時(shí)才能看出來(lái)

14. 什么是委托,它是如何跟協(xié)議 相關(guān)聯(lián)的

委托一般由一個(gè)類來(lái)實(shí)現(xiàn)并會(huì)將其賦給這個(gè)類的 delegate 屬性憨栽。實(shí)現(xiàn)委托的類必須要能夠響應(yīng)發(fā)送給委托的消息帜矾,那些消息通常是在委托的協(xié)議中指定的。一個(gè)類通常擁有不超過(guò)1個(gè)委托屑柔。但采用協(xié)議的個(gè)數(shù)沒(méi)有限制屡萤。

15. 分類和協(xié)議的比較

相同點(diǎn):可以在接口文件中聲明方法,但不能聲明變量和屬性锯蛀,在分類的實(shí)現(xiàn)中可以聲明私有的實(shí)例變量

不同點(diǎn):分類是綁定在一個(gè)特定類上的灭衷,而協(xié)議可以被任意類所采用次慢。分類是在運(yùn)行時(shí)被添加到某個(gè)特定類中旁涤。

16. 三個(gè)默認(rèn)的全局并發(fā)隊(duì)列分別是什么翔曲,在使用隊(duì)列時(shí),什么可以取代鎖

默認(rèn)優(yōu)先級(jí)劈愚、低優(yōu)先級(jí)瞳遍、高優(yōu)先級(jí)

使用線形隊(duì)列

17. OC 的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么? Category 是什么?重寫一個(gè)類的方式用繼承好還是分類好?為什么?

OC 的類不可以多重繼承;可以實(shí)現(xiàn)多個(gè)接口,通過(guò)實(shí)現(xiàn)多個(gè)接口可以完成 C++ 的多重繼承; Category 是類別菌羽,一般情況用分類好掠械,用 Category 去重寫類的方法,僅對(duì)本 Category 有效注祖,不會(huì)影響到其他類與原有類的關(guān)系猾蒂。

18. #import 跟 #include 又什么區(qū)別,@class 呢, #import<> 跟 #import “”又什么區(qū)別

#import 是 OC 導(dǎo)入頭文件的關(guān)鍵字是晨,#include 是 C/C++ 導(dǎo)入頭文件的關(guān)鍵字肚菠。使用 #import 頭文件會(huì)自動(dòng)只導(dǎo)入一次,不會(huì)交叉編譯罩缴,相當(dāng)于 #include 和 #pragma once ; @class 告訴編譯器某個(gè)類的聲明蚊逢,當(dāng)執(zhí)行時(shí),才去查看類的實(shí)現(xiàn)文件箫章,可以解決頭文件的相互包含; #import <> 用來(lái)包含系統(tǒng)的頭文件烙荷,#import"" 用來(lái)包含用戶頭文件

19. 屬性readwrite,readonly檬寂,assign终抽,retain,copy桶至,nonatomic 各是什么作用拿诸,在那種情況下用

(1) readwrite 是可讀可寫特性;需要生成getter方法和setter方法時(shí)

(2) readonly 是只讀特性 只會(huì)生成getter方法 不會(huì)生成setter方法 ;不希望屬性在類外改變

(3) assign 是賦值特性,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時(shí);

(4) retain 表示持有特性塞茅,setter方法將傳入?yún)?shù)先保留亩码,再賦值,傳入?yún)?shù)的retaincount會(huì)+1;

(5) copy 表示賦值特性野瘦,setter方法將傳入對(duì)象復(fù)制一份;需要完全一份新的變量時(shí)描沟。

(6) nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作鞭光,atomic表示多線程安全吏廉,一般使用nonatomic

20. 寫一個(gè)setter方法用于完成@property (nonatomic,retain)NSString *name,寫一個(gè)setter方法用于完成@property(nonatomic,copy)NSString *name

-(void)setName:(NSString*) str

{

[str retain];

[name release];

name=str;

}

-(void)setName:(NSString*)str

{

Id t=[str copy];

[name release];

Name = t;

}

21. 對(duì)于語(yǔ)句NSString*obj = [[NSData alloc] init]; obj在編譯時(shí)和運(yùn)行時(shí)分別時(shí)什么類型的對(duì)象

編譯時(shí)是 NSString 類型惰许,運(yùn)行時(shí)是 NSData 類型的對(duì)象

22. atomic 和 non-atomic 屬性的區(qū)別

atomic 本意是指屬性的存取方法是線程安全的席覆,并不保證整個(gè)對(duì)象是線程安全的。它僅限對(duì)setter汹买、getter方法是線程安全的佩伤。如果對(duì)一個(gè)@property(atomic,strong)NSMutableArray *arr;如果一個(gè)線程循環(huán)讀數(shù)據(jù)聊倔,一個(gè)線程循環(huán)寫數(shù)據(jù),肯定會(huì)產(chǎn)生內(nèi)存問(wèn)題生巡;

non-atomic 在自己管理內(nèi)存環(huán)境中耙蔑,解析的訪問(wèn)器保留并自動(dòng)釋放返回的值,若指定了 nonatomic 孤荣,那么訪問(wèn)器只是簡(jiǎn)單的返回這個(gè)值

23. 如何對(duì) iOS 設(shè)備進(jìn)行性能測(cè)試

Profile-> Instruments ->Time Profiler

24. 淺拷貝和深拷貝的區(qū)別

淺拷貝只復(fù)制指向?qū)ο蟮闹羔樀槟埃粡?fù)制引用對(duì)象本身

深拷貝復(fù)制引用對(duì)象本身

25. 類別的作用,繼承和類別在實(shí)現(xiàn)中有何區(qū)別

類別可以在不獲悉盐股、不改變?cè)瓉?lái)代碼的情況下往里面添加新的方法钱豁,只能添加,不能修改疯汁、刪除寥院,如果類別和原來(lái)類中的方法名產(chǎn)生沖突,則類別將覆蓋原來(lái)的方法涛目,因?yàn)轭悇e具有更高的優(yōu)先級(jí)秸谢。繼承可以增加、修改霹肝、刪除方法估蹄,并且可以增加屬性。

類別的主要作用:

1. 將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中沫换;

2. 創(chuàng)建對(duì)私有方法的向前引用臭蚁;

3.向?qū)ο筇砑臃钦絽f(xié)議

26. 類別和類擴(kuò)展的區(qū)別

category 和 extensions 的不同在于后者可以添加屬性,且后者添加的方法必須要實(shí)現(xiàn)讯赏,extensions 可以認(rèn)為是一個(gè)私有的 category垮兑。

27. 代理的作用

代理的目的是改變或傳遞控制鏈,允許一個(gè)類在某些特定時(shí)刻通知到其他類漱挎,而不需要獲取到那些類的指針系枪。可以減少框架的復(fù)雜度

28. frame 和 bounds 的區(qū)別

frame 指的是該 view 在父 view 坐標(biāo)系統(tǒng)中的位置和大小磕谅,參照點(diǎn)是父親的坐標(biāo)系統(tǒng)

bounds 指的是該 view 在本身坐標(biāo)系統(tǒng)中的位置和大小私爷,參照點(diǎn)是本身坐標(biāo)系統(tǒng)

29. 方法和選擇器的區(qū)別

selector 是一個(gè)方法的名字,method 包含了方法的名字和實(shí)現(xiàn)

30. 在 iPhone 應(yīng)用中如何保存數(shù)據(jù)

1. 通過(guò) web 服務(wù)膊夹,保存在服務(wù)器上衬浑;

2. 通過(guò) NSCoder 固化機(jī)制,將對(duì)象保存在文件中放刨;

3. 通過(guò) SQLite 或 CoreDate 保存在數(shù)據(jù)庫(kù)中

31. 什么是 NSManagedObject 模型工秩,什么是 NSManagedObjectContext?

NSManagedObject 是 NSObject 的子類,也是 CoreData 的重要組成部分助币,它是一個(gè)通用類浪听,實(shí)現(xiàn)了 CoreData 模型層所需的基本功能,用戶可通過(guò)子類化 NSManagedObject奠支,建立自己的數(shù)據(jù)模型馋辈。

NSManagedObjectContext 對(duì)象負(fù)責(zé)應(yīng)用和數(shù)據(jù)庫(kù)之間的交互

32. 手機(jī)明明還有內(nèi)存抚芦,但為何還會(huì)提示內(nèi)存不足倍谜?

手機(jī)廠商通常會(huì)將運(yùn)行內(nèi)存(RAM)和存儲(chǔ)內(nèi)存(ROM)統(tǒng)稱為手機(jī)內(nèi)存,手機(jī)提示內(nèi)存不足叉抡,并不指明是運(yùn)行內(nèi)存還是存儲(chǔ)內(nèi)存尔崔,事實(shí)上,往往是運(yùn)行內(nèi)存不足褥民。所以季春,不少人發(fā)現(xiàn)手機(jī)仍有很多內(nèi)存,其實(shí)這部分是存儲(chǔ)內(nèi)存消返。

33. 在項(xiàng)目中什么時(shí)候選擇使用 GCD载弄, 什么時(shí)候選擇 NSOperation

NSOperation 的優(yōu)點(diǎn)是對(duì)線程的高度抽象,在項(xiàng)目中使用它撵颊,會(huì)使得項(xiàng)目的程序結(jié)構(gòu)更好宇攻,子類化 NSOperation 的設(shè)計(jì)思路,是具有面向?qū)ο蟮膬?yōu)點(diǎn)倡勇,使得實(shí)現(xiàn)是多線程支持逞刷,而接口簡(jiǎn)單,建議在復(fù)雜的項(xiàng)目中使用妻熊;

GCD 的優(yōu)點(diǎn)是 GCD 本身非常簡(jiǎn)單夸浅、易用、更加輕量級(jí)扔役,對(duì)于不復(fù)雜的多線程操作帆喇,會(huì)節(jié)省代碼量,而 Block 參數(shù)的使用亿胸,會(huì)使得代碼更為易懂番枚,建議在簡(jiǎn)單的項(xiàng)目中使用。

34. GCD 和 NSOperation 的區(qū)別

1. GCD 是底層的 C 語(yǔ)言構(gòu)成的 API 损敷, 而 NSOperationQueue 及相關(guān)對(duì)象是 OC 的對(duì)象葫笼。在 GCD 中,在隊(duì)列中執(zhí)行的是由 block 構(gòu)成的任務(wù)拗馒,這是一個(gè)輕量級(jí)的數(shù)據(jù)結(jié)構(gòu)路星,而 NSOperation 作為一個(gè)對(duì)象,為我們提供了更多的選擇;

2. 在 NSOperationQueue 中洋丐,我們可以隨時(shí)取消已經(jīng)設(shè)定要準(zhǔn)備執(zhí)行的任務(wù)呈昔,當(dāng)然,已經(jīng)開始的任務(wù)就無(wú)法阻止了友绝,而 GCD 沒(méi)法停止已經(jīng)加入 queue 的 block (其實(shí)是有的堤尾,但需要許多復(fù)雜的代碼);

3. NSOperation 能夠方便的設(shè)置依賴關(guān)系迁客,我們可以讓一個(gè) Operation 依賴于另一個(gè) Operation郭宝,這樣的話盡管兩個(gè) Operation 處于同一個(gè)并行隊(duì)列中,但前者會(huì)直到后者執(zhí)行完畢后再執(zhí)行掷漱;

4. 我們能將 KVO 應(yīng)用在 NSOperation 中粘室,可以監(jiān)聽一個(gè) Operation 是否完成或取消,這樣能比 GCD 更加有效的掌控我們執(zhí)行的后臺(tái)任務(wù)卜范;

5. 在 NSOperation 中衔统,我們能夠設(shè)置 NSOperation 的 priority 優(yōu)先級(jí),能夠使同一個(gè)并行隊(duì)列中的任務(wù)區(qū)分先后的執(zhí)行海雪,而在 GCD 中锦爵,我們只能區(qū)分不同任務(wù)隊(duì)列的優(yōu)先級(jí),如果要區(qū)分 block 任務(wù)的優(yōu)先級(jí)奥裸,也需要大量復(fù)雜的代碼险掀;

6. 我們能夠?qū)?NSOperation 進(jìn)行繼承,在這之上添加成員變量與方法刺彩,提高整個(gè)代碼的復(fù)用度迷郑,這比簡(jiǎn)單的將 block 任務(wù)排入執(zhí)行隊(duì)列更有自由度,能夠在其之上添加更多自定制的功能创倔。

35. ViewController的didReceiveMemoryWarning怎么被調(diào)用

[supper didReceiveMemoryWarning];

36. 用預(yù)處理指令#define聲明一個(gè)常數(shù)嗡害,用以表明1年中有多少秒(忽略閏年問(wèn)題)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

37. const 意味著 “只讀” ,下面聲明都是什么意思

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

前兩個(gè)的作用是一樣畦攘,a是一個(gè)常整型數(shù)霸妹。

第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的知押,但指針可以)叹螟。

第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的台盯,但指針是不可修改的)罢绽。

最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的静盅,同時(shí)指針也是不可修改的)良价。

38. 關(guān)鍵字volatile有什么含意?并給出三個(gè)不同的例子

一個(gè)定義為 volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了明垢。精確地說(shuō)就是蚣常,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份痊银。

下面是volatile變量的幾個(gè)例子:

并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)

一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)

多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

39. 一個(gè)參數(shù)既可以是const還可以是volatile嗎抵蚊? 一個(gè)指針可以是volatile 嗎?解釋為什么溯革。

(1)是的贞绳。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖凎拚铡K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它熔酷。

(2)是的孤紧。盡管這并不很常見(jiàn)豺裆。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)

40. static 關(guān)鍵字的作用

(1)函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量号显,該變量的內(nèi)存只被分配一次臭猜,

因此其值在下次調(diào)用時(shí)仍維持上次的值;

(2)在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問(wèn)押蚤,但不能被模塊外其它函數(shù)訪問(wèn)蔑歌;

(3)在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明

它的模塊內(nèi)揽碘;

(4)在類中的 static 成員變量屬于整個(gè)類所擁有次屠,對(duì)類的所有對(duì)象只有一份拷貝;

(5)在類中的 static 成員函數(shù)屬于整個(gè)類所擁有雳刺,這個(gè)函數(shù)不接收 this 指針劫灶,因而只能訪問(wèn)類的static 成員變量。

41. 進(jìn)程之間通信的途徑

共享存儲(chǔ)系統(tǒng)消息傳遞系統(tǒng)管道:以文件系統(tǒng)為基礎(chǔ)

42. iOS 的系統(tǒng)架構(gòu)

iOS 的系統(tǒng)架構(gòu)分為:核心操作系統(tǒng)層掖桦、核心服務(wù)層本昏、媒體層和 Cocoa 界面服務(wù)層

43. Cocoa Touch 提供了哪幾種 Core Animation 過(guò)度類型

交叉淡化、推擠枪汪、顯示和覆蓋

44. Quartz ?2D 的繪圖功能的三個(gè)核心概念是什么并簡(jiǎn)述其作用

1. 上下文:主要用于描述圖形寫入哪里涌穆;

2. 路徑:是在圖層上繪制的內(nèi)容;

3. 狀態(tài):用于保存配置變換的值雀久、填充和輪廓宿稀,alpha 值等

45. 通知與協(xié)議的區(qū)別

協(xié)議有控制鏈的關(guān)系,通知沒(méi)有赖捌;

通知可以1對(duì)多祝沸,代理1對(duì)1;

代理的接受者可以返回值給發(fā)送者,通知不能奋隶;

代理比通知效率高

46. 什么是簡(jiǎn)便構(gòu)造方法

簡(jiǎn)便構(gòu)造方法一般由 Cocoa Touch 框架提供擂送,如NSNumber的 + numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:

Foundation下大部分類均有簡(jiǎn)便構(gòu)造方法,我們可以通過(guò)簡(jiǎn)便構(gòu)造方法唯欣,獲得系統(tǒng)給我們創(chuàng)建好的對(duì)象嘹吨,并且不需要手動(dòng)釋放。

47. 簡(jiǎn)述視圖控制器的生命周期

按照以下順序執(zhí)行:

1. initWithCoder: 通過(guò) nib 文件初始化時(shí)觸發(fā)境氢;

2. awakeFromNib: nib 文件被加載的時(shí)候蟀拷,會(huì)發(fā)生一個(gè) awakeFromNib 的消息到 nib 文件中的每個(gè)對(duì)象;

3. loadView:開始加載視圖控制器自帶的 view萍聊。當(dāng)用到控制器 view 時(shí)问芬,會(huì)調(diào)用 view 的 get 方法,在 get 方法內(nèi)部寿桨,先判斷 view 是否已創(chuàng)建此衅,若已存在,則直接返回存在的 view亭螟,若不存在挡鞍,則調(diào)用控制器的 loadView 方法,在控制器沒(méi)有被銷毀的情況下预烙,loadView 可能會(huì)被執(zhí)行多次墨微;

4. viewDidLoad:視圖控制器的 view 被加載完成。當(dāng) loadView 執(zhí)行完畢扁掸,view 被創(chuàng)建成功后就會(huì)執(zhí)行 viewDidLoad 方法翘县,與 loadView 一樣,可能會(huì)被執(zhí)行多次谴分。比如 A push 到 B锈麸,此時(shí)窗口顯示的是 B 的 View,此時(shí)若收到內(nèi)存警告狸剃,我們一般會(huì)將 A 中沒(méi)用到的變量及 View 銷毀掉掐隐,之后當(dāng) B pop 回 A 時(shí),就會(huì)再次執(zhí)行 loadView 與 viewDidLoad 方法钞馁;

5. viewWillAppear:視圖控制器的 view 將要顯示在 window 上虑省;

6. updateViewConstraints:視圖控制器的 view 開始更新 AutoLayout 約束;

7. viewWillLayoutSubviews:視圖控制器的 view 將要更新內(nèi)容視圖的位置僧凰;

8. viewDidLayoutSubviews:視圖控制器的 view 已經(jīng)更新視圖的位置探颈;

9. viewDidAppear:視圖控制器的 view 已經(jīng)展示到 window 上;

10. viewWillDisappear:視圖控制器的 view 將要從 window 上消失训措;

11. viewDidDisappear:視圖控制器的 view 已經(jīng)從 window 上消失伪节。

48. 動(dòng)畫的基本類型有哪些

隱式動(dòng)畫和顯式動(dòng)畫光羞,在做 iOS 動(dòng)畫時(shí),當(dāng)修改非 RootLayer 屬性(比如位置怀大、背景色)會(huì)默認(rèn)產(chǎn)生隱式動(dòng)畫纱兑。

49. UIView 和 CALayer 的關(guān)系

UIView 是 iOS 界面元素的基礎(chǔ),看得見(jiàn)摸得著的基本都是 UIView化借,比如一個(gè)按鈕潜慎、一個(gè)圖標(biāo)等。其實(shí) UIView 之所以能顯示在屏幕上蓖康,完全是因?yàn)樗鼉?nèi)部有一個(gè)圖層铐炫。當(dāng)創(chuàng)建一個(gè) UIView 對(duì)象時(shí),UIView 內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)圖層(即 CALayer 對(duì)象)蒜焊,通過(guò) UIView 的 layer 屬性可以訪問(wèn)這個(gè)層倒信。當(dāng) UIView 需要顯示到屏幕上時(shí),會(huì)調(diào)用 drawRect 方法進(jìn)行繪圖泳梆,并將所有內(nèi)容繪制在自己的圖層上鳖悠,繪圖完畢后,系統(tǒng)會(huì)將圖層拷貝到屏幕上鸭丛,于是完成了 UIView 的顯示竞穷。換句話說(shuō)唐责,UIView 本身不具備顯示的功能鳞溉,是它內(nèi)部的層才有顯示功能。

CALayer 內(nèi)部控制兩個(gè)屬性?presentationLayer 和 modelLayer鼠哥,modelLayer 為當(dāng)前 layer 真實(shí)的狀態(tài)熟菲,presentationLayer 為當(dāng)前 layer 在屏幕上展示的狀態(tài)。presentationLayer 會(huì)在每次屏幕刷新時(shí)更新狀態(tài)朴恳,如果有動(dòng)畫則根據(jù)動(dòng)畫獲取當(dāng)前狀態(tài)進(jìn)行繪制抄罕,動(dòng)畫移除后則取 modelLayer 的狀態(tài)。

CALayer 是定義在 QuartzCore 框架中的于颖,CGImageRef呆贿、CGColorRef 兩種數(shù)據(jù)類型是定義在 CoreGraphics 框架中的,而 UIColor 森渐、UIImage 是定義在 UIKit 框架中的做入,QuartzCore 和 CoreGraphics 是可以跨平臺(tái)使用的,在 iOS 和 Mac OS X 上都能使用同衣,但 UIKit 只能在 iOS 中使用竟块。所以為了保證可移植性,QuartzCore 不能使用 UIImage耐齐、UIColor浪秘,只能使用 CGImageRef蒋情、CGColorRef,這就是為什么 layer 對(duì)邊框顏色設(shè)置時(shí)需要加上 CGColor 方法耸携。

區(qū)別:

UIView 可以響應(yīng)事件而 CALayer 不能棵癣;

CALayer 性能會(huì)高一些,更加輕量級(jí)夺衍;

UIView 主要是對(duì)顯示內(nèi)容的管理浙巫,而CALayer 主要側(cè)重顯示內(nèi)容的繪制;

在做 iOS 動(dòng)畫時(shí)刷后,當(dāng)修改非 RootLayer 屬性(比如位置的畴、背景色)會(huì)默認(rèn)產(chǎn)生隱式動(dòng)畫,而修改 UIView 則不會(huì)尝胆,這是因?yàn)槿魏慰蓜?dòng)畫的 layer 屬性改變時(shí)丧裁,layer 都會(huì)尋找并運(yùn)行合適 action 來(lái)實(shí)行這個(gè)改變。

UIView 和 CALayer 是處于一個(gè)平級(jí)的關(guān)系含衔。其實(shí)原因很簡(jiǎn)單, 是為了職責(zé)分離, 也算是模塊化劃分吧, 因?yàn)樵?Mac OS?當(dāng)中, 并沒(méi)有?UIView?這個(gè)類, 所以并不能處理?Touch?事件, 但卻有?CALayer, 所以蘋果為了能夠讓?Mac OS?和?iOS?兩個(gè)系統(tǒng)相互共享代碼, 直接把?CALayer?給獨(dú)立出來(lái)了煎娇。

50. UIImage 的初始化方法有哪些及區(qū)別

1. ImageNamed 是 UIImage 的類方法,系統(tǒng)先檢查緩存中是否存在該名字的圖像贪染,若存在則直接返回缓呛,若不存在,則會(huì)先加載到緩存中杭隙,再返回該對(duì)象哟绊。適合頻繁用到某一圖片時(shí)使用。若我們需要短時(shí)間內(nèi)頻繁的加載一些一次性的圖像痰憎,最好不要使用這種方法票髓。

優(yōu)點(diǎn)是方便快捷,只用第一次使用的時(shí)候稍慢铣耘,接下來(lái)再使用就會(huì)稍微快點(diǎn)洽沟。缺點(diǎn)是如果在當(dāng)前工程中只使用一次,就會(huì)浪費(fèi)內(nèi)存蜗细。

[UIImage imageNamed:]加載圖片有個(gè)好處在于可以立刻解壓圖片而不用等到繪制的時(shí)候裆操。但是[UIImage imageNamed:]方法有另一個(gè)非常顯著的好處:它在內(nèi)存中自動(dòng)緩存了解壓后的圖片,即使你自己沒(méi)有保留對(duì)它的任何引用炉媒。

對(duì)于iOS應(yīng)用那些主要的圖片(例如圖標(biāo)课舍,按鈕和背景圖片)扣唱,使用[UIImage imageNamed:]加載圖片是最簡(jiǎn)單最有效的方式。在nib文件中引用的圖片同樣也是這個(gè)機(jī)制,所以你很多時(shí)候都在隱式的使用它模暗。

但是[UIImage imageNamed:]并不適用任何情況官硝。它為用戶界面做了優(yōu)化割卖,但是并不是對(duì)應(yīng)用程序需要顯示的所有類型的圖片都適用。有些時(shí)候你還是要實(shí)現(xiàn)自己的緩存機(jī)制茅郎,原因如下:

[UIImage imageNamed:]方法僅僅適用于在應(yīng)用程序資源束目錄下的圖片,但是大多數(shù)應(yīng)用的許多圖片都要從網(wǎng)絡(luò)或者是用戶的相機(jī)中獲取或渤,所以[UIImage imageNamed:]就沒(méi)法用了系冗。

[UIImage imageNamed:]緩存用來(lái)存儲(chǔ)應(yīng)用界面的圖片(按鈕,背景等等)薪鹦。如果對(duì)照片這種大圖也用這種緩存掌敬,那么iOS系統(tǒng)就很可能會(huì)移除這些圖片來(lái)節(jié)省內(nèi)存。那么在切換頁(yè)面時(shí)性能就會(huì)下降池磁,因?yàn)檫@些圖片都需要重新加載奔害。對(duì)傳送器的圖片使用一個(gè)單獨(dú)的緩存機(jī)制就可以把它和應(yīng)用圖片的生命周期解耦。

[UIImage imageNamed:]緩存機(jī)制并不是公開的地熄,所以你不能很好地控制它华临。例如,你沒(méi)法做到檢測(cè)圖片是否在加載之前就做了緩存端考,不能夠設(shè)置緩存大小雅潭,當(dāng)圖片沒(méi)用的時(shí)候也不能把它從緩存中移除。

2. imageWithContentsOfFile 和 initWithContentsOfFile 一個(gè)是類方法却特,一個(gè)是對(duì)象方法扶供,這兩種是通過(guò)圖片來(lái)加載圖片的,沒(méi)有緩存裂明。當(dāng)收到內(nèi)存警告的時(shí)候椿浓,系統(tǒng)可能會(huì)將 UIImage 內(nèi)部的存儲(chǔ)圖像的內(nèi)存釋放,下一次需要的時(shí)候重新加載漾岳。

3. imageWithCGImage:scale:orientation:轰绵,該方法使用一個(gè) CGImageRef 創(chuàng)建 UIImage,在創(chuàng)建時(shí)還可以指定方法倍數(shù)以及旋轉(zhuǎn)方向尼荆。

51. 協(xié)議和分類中怎么使用 property

在協(xié)議中使用 @property 只會(huì)生成 setter 和 getter 方法聲明,我們使用屬性的目的就是希望遵守我們協(xié)議對(duì)象能夠?qū)崿F(xiàn)該屬性唧垦。內(nèi)部是沒(méi)有實(shí)例變量的捅儒,并且你不能去重定義它,只能在 setter 和 getter 里處理振亮;

在分類中使用 @property 也只是會(huì)生成 setter 和 getter 方法聲明巧还,如果真需要在分類增加屬性的實(shí)現(xiàn)需要借助兩個(gè)運(yùn)行時(shí)的函數(shù) objc_setAssociatedObject 和 objc_getAssociatedObject

建立分類后,h文件:@property (nonatomic , strong) NSString * str;m文件導(dǎo)入運(yùn)行時(shí)#import設(shè)置中轉(zhuǎn)站:static char AddressKey;

寫set和get方法:

-(NSString *)str{

return objc_getAssociatedObject(self, &AddressKey);

}

-(void)setStr:(NSString *)str{

objc_setAssociatedObject(self, &AddressKey, str,OBJC_ASSOCIATION_COPY_NONATOMIC);

}

52. 簡(jiǎn)述 Runloop 原理

一個(gè) runloop 是一個(gè)事件處理環(huán)坊秸,系統(tǒng)利用這個(gè)環(huán)來(lái)安排事務(wù)麸祷,協(xié)調(diào)輸入的各種事件。Runloop 的目的是讓你的線程在有工作的時(shí)候忙碌褒搔,沒(méi)有工作的時(shí)候休眠阶牍。線程和 Runloop 之間是以鍵值對(duì)的形式一一對(duì)應(yīng)的喷面,其中 key 是 thread,value 是 runloop走孽。Runloop 實(shí)際上就是一個(gè)對(duì)象惧辈,這個(gè)對(duì)象管理了其需要處理的事件和消息,并提供了一個(gè)入口函數(shù)來(lái)執(zhí)行上面 Event Loop 的邏輯磕瓷。線程執(zhí)行了這個(gè)函數(shù)后盒齿,就會(huì)一直處于這個(gè)函數(shù)內(nèi)部 “接受消息->等待->處理” 的循環(huán)中,直到這個(gè)循環(huán)結(jié)束(比如傳入 quit 的消息)困食,函數(shù)返回边翁。它提供了 NSRunLoop 和 CFRunLoopRef 兩個(gè)對(duì)象。

CFRunLoopRef 是在 CoreFoundation 框架內(nèi)的硕盹,它提供了純 C 函數(shù)的 API倒彰,所有這些 API 都是線程安全的。

NSRunloop 是基于 CFRunLoopRef 的封裝莱睁,提供了面向?qū)ο蟮?API待讳,但是這些 API 不是線程安全的。

53. iOS 內(nèi)存分區(qū)和 block 的使用及內(nèi)存位置

iOS 內(nèi)存分區(qū)有5個(gè):棧區(qū)仰剿、堆區(qū)创淡、全局區(qū)、常量區(qū)南吮、代碼區(qū)琳彩。這5個(gè)區(qū)在物理上是分開的。

棧區(qū)(stack):這一塊區(qū)域系統(tǒng)會(huì)自己來(lái)管理部凑,我們不用干預(yù)露乏,主要存一些局部變量以及函數(shù)跳轉(zhuǎn)時(shí)的現(xiàn)場(chǎng)保護(hù),因此大量的局部變量涂邀、深遞歸瘟仿、函數(shù)循環(huán)調(diào)用都可能耗盡內(nèi)存而造成運(yùn)行崩潰。優(yōu)點(diǎn)是快速高效比勉,缺點(diǎn)是時(shí)有限制劳较,數(shù)據(jù)不靈活(先進(jìn)后出)。

堆區(qū)(heap):與棧區(qū)相對(duì)浩聋,這一塊由開發(fā)人員管理观蜗,存儲(chǔ)一些自己創(chuàng)建的對(duì)象。若程序員不釋放衣洁,程序結(jié)束時(shí)墓捻,可能會(huì)由操作系統(tǒng)回收。優(yōu)點(diǎn)是靈活方便坊夫、數(shù)據(jù)適應(yīng)面廣泛砖第,但效率有一定降低(順序隨意)撤卢。

全局區(qū)(又叫靜態(tài)區(qū) static):全局變量和靜態(tài)變量都存儲(chǔ)在這里,已經(jīng)初始化和沒(méi)初始化的變量會(huì)分開存儲(chǔ)在相鄰區(qū)域厂画,程序結(jié)束后由系統(tǒng)釋放凸丸。

常量區(qū):存儲(chǔ)常量字符串和 const 常量,程序結(jié)束后由系統(tǒng)釋放袱院。

代碼區(qū):存我們寫的代碼屎慢,二進(jìn)制。

block 會(huì)根據(jù)情況有兩種存儲(chǔ)位置忽洛,一種在代碼區(qū)腻惠,一種在堆區(qū):

1. 如果 block 塊沒(méi)有訪問(wèn)處于棧區(qū)的變量,比如局部變量欲虚,也沒(méi)有訪問(wèn)堆區(qū)的變量集灌,比如我們創(chuàng)建的對(duì)象,那它就存在代碼區(qū)复哆,即使訪問(wèn)了全局變量欣喧,也依然存在代碼區(qū);

2. 如果訪問(wèn)了棧區(qū)或堆區(qū)的變量梯找,那就會(huì)存在堆區(qū)(實(shí)際上是存在棧區(qū)唆阿,在 ARC 下,當(dāng)被賦值給 strong 對(duì)象或 block 類型的變量時(shí)锈锤,會(huì)觸發(fā) [block copy]驯鳖,將其拷貝到堆區(qū))。

關(guān)于存在堆區(qū)的情況久免,需要注意的是浅辙,堆區(qū)是不斷變化的,不斷有變量被創(chuàng)建和釋放阎姥。如果 block 沒(méi)有強(qiáng)引用记舆,那隨時(shí)也會(huì)被銷毀,這就導(dǎo)致一旦在銷毀后訪問(wèn) block丁寄,程序會(huì)崩潰氨淌。所以定義 block 時(shí),最好用 strong 或 copy 修飾伊磺,且在使用時(shí)最好先判斷一下 block 是否為空。

既然用了 strong 修飾删咱,那另一個(gè)問(wèn)題就來(lái)了屑埋,那就是循環(huán)引用問(wèn)題

當(dāng)使用 strong 修飾后,self 會(huì)強(qiáng)引用 block痰滋,而如果在 block 中又需要訪問(wèn) self 的一些屬性或方法摘能,從而調(diào)用了 self续崖,這時(shí) self 和 block 就會(huì)進(jìn)入循環(huán)引用,導(dǎo)致內(nèi)存溢出团搞。所以需要在用到 self 時(shí)严望,事先將 self 用 __weak 修飾,從而打破循環(huán)引用逻恐。

但這還不夠像吻,在多線程下,單單使用 weakself 复隆,可能前一刻 weakself 還在拨匆,后面需要使用的時(shí)候卻被釋放了,畢竟弱引用是不穩(wěn)定的挽拂,這時(shí)候需要使用 __strong 來(lái)在 block 中修飾:

__weak __typeof(self) *weakSelf = self;

self.block = ^{

__strong __typeof(self) strongSelf = weakSelf;

if (strongSelf) {

strongSelf.str = @"123";

}

// 如果不用了惭每,應(yīng)置為空

strongSelf.block = nil;

};

54. 什么是響應(yīng)者鏈(UIResponder)

UIResponder 類是專門用來(lái)響應(yīng)用戶的操作,處理各種事件亏栈,包括觸摸事件台腥、運(yùn)動(dòng)事件、遠(yuǎn)程控制事件绒北。而 UIApplication黎侈、UIView、UIViewController 這幾個(gè)類是直接繼承自 UIResponder 的镇饮,所以這些類都可以響應(yīng)事件蜓竹。當(dāng)用戶觸發(fā)某一事件時(shí),UIKit 會(huì)創(chuàng)建一個(gè) UIEvent 事件對(duì)象储藐,事件對(duì)象會(huì)加入到 FIFO 先進(jìn)先出的隊(duì)列中俱济,UIApplication 對(duì)象處理事件時(shí),會(huì)從隊(duì)列頭部取出一個(gè)事件對(duì)象進(jìn)行分發(fā)钙勃。

(1) 觸摸事件蛛碌,touchesBegan 等和 UIGestureReconizer 手勢(shì),UIApplication? 會(huì)首先把事件交給 KeyWindow辖源,window 會(huì)將事件交給 UIGestureReconizer 處理蔚携,如果它識(shí)別出了傳遞過(guò)來(lái)的事件,則會(huì)交給對(duì)應(yīng)的 target 去處理克饶,事件不會(huì)再傳遞酝蜒。若沒(méi)有識(shí)別出來(lái),事件會(huì)傳遞到視圖樹形結(jié)構(gòu)矾湃,會(huì)分別尋找接受者和事件響應(yīng)這兩個(gè)步驟:

1. 在 iOS 視圖樹形結(jié)構(gòu)中找到最終的接受者亡脑,也就是觸摸事件發(fā)生的那個(gè)最上層的 View 上,這一過(guò)程稱為 hit-testing(測(cè)試命中),通過(guò)一層層的遍歷找到最終的命中視圖稱為 hit-test view霉咨;

2. 找到了 hit-test view 蛙紫,下一步就是響應(yīng)事件。說(shuō)明一下途戒,對(duì)于觸摸事件來(lái)說(shuō)坑傅,無(wú)論 View 是否處理事件,即使是 Application 通過(guò) [application beginIgnoringInteractionEvents] 忽略了觸摸事件喷斋,上面 hit-testing 過(guò)程依然存在唁毒,它只影響第二個(gè)步驟事件響應(yīng)的過(guò)程。

如果整個(gè)響應(yīng)者鏈結(jié)束继准,都沒(méi)有對(duì)事件做處理枉证,那么該事件會(huì)被丟棄。

總結(jié)一下響應(yīng)者鏈的傳遞過(guò)程:由第一響應(yīng)者(對(duì)于觸摸事件來(lái)說(shuō)是 hit-test view)開始向上傳遞移必。如果該視圖是控制器的根視圖室谚,先傳遞給控制器,再傳遞給父視圖崔泵;如果不是控制器的根視圖秒赤,直接傳遞給父視圖。只要在響應(yīng)者的處理方法里面調(diào)用父類的方法憎瘸,就可以讓多個(gè)視圖和控制器響應(yīng)同一個(gè)事件入篮,響應(yīng)者鏈條的根本目的是:共享事件,讓多個(gè)視圖和控制器可以對(duì)同一事件做不同的處理幌甘。

(2)運(yùn)動(dòng)事件潮售,motionBegan 等,這里的運(yùn)動(dòng)事件特指 shake 事件锅风,用于手機(jī)搖動(dòng)觸發(fā)手機(jī)內(nèi)部的加速器酥诽。響應(yīng)者鏈條對(duì) shake 事件同樣適用,只不過(guò)皱埠,沒(méi)有 hit-testing 過(guò)程肮帐,如果當(dāng)前顯示的視圖界面沒(méi)有一個(gè) view 聲明為第一響應(yīng)者(調(diào)用 becomeFirstResponder 申明并且 View 需要重寫canBecomeFirstResponder 方法返回 YES,默認(rèn)返回為 NO )边器,默認(rèn)當(dāng)前視圖控制器為第一響應(yīng)者训枢,并將事件沿著響應(yīng)者鏈條傳遞,直到被處理忘巧。如果有視圖聲明為第一響應(yīng)者恒界,就從該視圖開始傳遞事件直到被處理,如果該事件最終沒(méi)有被處理并且 UIApplication 的applicationSupportsShakeToEdit 屬性為 YES(默認(rèn)就是 YES ),當(dāng)鍵盤顯示的時(shí)候,系統(tǒng)會(huì)有一個(gè)是否撤銷正在輸入的警告砚嘴。就是微信和 QQ 上在輸入的時(shí)候搖動(dòng)手機(jī)提示撤銷輸入的那種效果仗处。

55. 什么是類對(duì)象結(jié)構(gòu)

Class 是一個(gè)指向 objc_class 結(jié)構(gòu)體的指針眯勾。這個(gè)結(jié)構(gòu)體主要包含:

1. isa:它指向 metaClass (元類)枣宫;

2. super_class:指向該類的父類婆誓,若該類已經(jīng)是最頂層的根類,則為NULL也颤;

3. cache:用于緩存最近使用的方法洋幻。在我們每次調(diào)用過(guò)一個(gè)方法后,這個(gè)方法就被緩存到 cache 列表中翅娶,下次調(diào)用時(shí) runtime 就會(huì)優(yōu)先去 cache 中查找文留。若 cache 沒(méi)有才去 methodLists 中查找方法;

4. version:我們可以使用這個(gè)字段來(lái)提供類的版本信息竭沫。這對(duì)于對(duì)象序列化很有用燥翅,它可以讓我們識(shí)別出不同類定義版本中實(shí)例變量布局的改變。

Object 是一個(gè)指向 objc_object 結(jié)構(gòu)體的指針蜕提。這個(gè)結(jié)構(gòu)體只用一個(gè)字段 isa森书,它指向它的類結(jié)構(gòu)。當(dāng)我們向一個(gè)對(duì)象發(fā)送消息時(shí)谎势,運(yùn)行時(shí)庫(kù)會(huì)根據(jù)對(duì)象的 isa 指針找到這個(gè)對(duì)象所屬的類凛膏。運(yùn)行時(shí)庫(kù)會(huì)在類的方法列表及父類的方法列表中尋找與消息對(duì)應(yīng)的 selector 指向的方法,找到后運(yùn)行這個(gè)方法脏榆。id 是一個(gè)指向 objc_object 結(jié)構(gòu)體的指針猖毫。

所以類自身也是一個(gè)對(duì)象,我們可以向其發(fā)送消息(調(diào)用類方法)须喂。既然是對(duì)象吁断,它也有個(gè)指向其類的 isa 指針,而這個(gè)類就是 metaClass(元類)坞生。元類存儲(chǔ)著一個(gè)類的所有類方法仔役,每個(gè)類都會(huì)有一個(gè)單獨(dú)的元類。而元類也是一個(gè)類恨胚,可以向它發(fā)送消息骂因,那它的 isa 又指向什么呢?為了不讓這種結(jié)構(gòu)無(wú)限延伸下去赃泡,蘋果規(guī)定任何 NSObject 繼承體系下的元類都使用 NSObject 的元類作為自己的所屬類寒波,而基類的元類的 isa 指向它自己。

56. int 和 NSInteger 的區(qū)別

NSInteger 會(huì)根據(jù)系統(tǒng)的位數(shù)(32 或 64)自動(dòng)選擇 int 的最大數(shù)值(int 或 long)升熊。

57. 死鎖

死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中俄烁,因爭(zhēng)奪資源而造成一種互相等待的現(xiàn)象。

造成死鎖的原因:

1. 系統(tǒng)資源不足级野;

2. 進(jìn)程運(yùn)行推進(jìn)的順序不合適页屠;

3. 資源分配不當(dāng)

產(chǎn)生死鎖的必要條件:

1. 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用;

2.請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放辰企;

3.不剝奪條件:進(jìn)程已獲得的資源风纠,在未使用完之前,不能強(qiáng)行剝奪牢贸;

4.循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系

58. HTTPS 的傳輸過(guò)程

HTTPS 由 HTTP + SSL/TLS 組成竹观,也就是在 HTTP 上又加了一層處理加密信息的模塊

SSL:(Secure Socket Layer,安全套接字層)潜索,位于可靠的面向連接的網(wǎng)絡(luò)層協(xié)議和應(yīng)用層協(xié)議之間的一種協(xié)議層臭增。SSL 通過(guò)互相認(rèn)證、使用數(shù)字簽名確保完整性竹习、使用加密確保私密性誊抛,以實(shí)現(xiàn)客戶端和服務(wù)器之間的安全通訊。該協(xié)議由兩層組成:SSL 記錄協(xié)議和 SSL 握手協(xié)議整陌。

TLS:(Transport Layer Security拗窃,傳輸層安全協(xié)議),用于兩個(gè)應(yīng)用程序之間提供保密性和數(shù)據(jù)完整性蔓榄。該協(xié)議由兩層組成:TLS 記錄協(xié)議和 TLS 握手協(xié)議并炮。

傳輸過(guò)程:

1. 客戶端發(fā)起 HTTPS 請(qǐng)求;

2. 服務(wù)端配置甥郑,采用 HTTPS 協(xié)議的服務(wù)器必須要有一套數(shù)字證書逃魄,就是一套公鑰和私鑰。公鑰和私鑰就像一把鎖和鑰匙澜搅,全世界只有你有這把鑰匙伍俘,你可以把鎖給別人用它鎖上重要的東西然后發(fā)給你,因?yàn)橹挥心阌需€匙勉躺,所以只用你能看到被鎖上的東西癌瘾;

3. 傳送證書,服務(wù)器向客戶端發(fā)送公鑰饵溅,其中包含了證書的頒發(fā)機(jī)構(gòu)妨退、過(guò)期時(shí)間等;

4. 客戶端解析證書蜕企,這部分工作由客戶端的 TLS 來(lái)完成咬荷,首先驗(yàn)證公鑰是否有效,若發(fā)現(xiàn)異常轻掩,則會(huì)彈出警告框幸乒,提示證書存在問(wèn)題。若證書沒(méi)有問(wèn)題唇牧,則會(huì)生成一個(gè)隨機(jī)值罕扎,然后用證書對(duì)該隨機(jī)值進(jìn)行加密聚唐。就像用鎖頭把隨機(jī)值鎖上,除非有鑰匙腔召,否則看不到被鎖住的內(nèi)容杆查;

5. 客戶端傳送加密信息,客戶端將用證書加密后的隨機(jī)值發(fā)給服務(wù)端宴咧,以后就可以通過(guò)這個(gè)隨機(jī)值來(lái)進(jìn)行加密解密了根灯;

6. 服務(wù)端解密信息,服務(wù)端用私鑰解密后掺栅,得到客戶端傳過(guò)來(lái)的隨機(jī)值,然后把內(nèi)容通過(guò)該值進(jìn)行對(duì)稱加密纳猪。所謂對(duì)稱加密就是將信息和這個(gè)隨機(jī)值通過(guò)某種算法混合在一起氧卧,這樣除非知道這個(gè)隨機(jī)值,不然無(wú)法獲取內(nèi)容氏堤,而正好客戶端和服務(wù)端都知道這個(gè)隨機(jī)值沙绝,所以只要加密算法夠強(qiáng)大,隨機(jī)值夠復(fù)雜鼠锈,數(shù)據(jù)就夠安全闪檬;

7. 傳輸加密后的信息,服務(wù)端將加密信息發(fā)給客戶端购笆;

8. 客戶端解密信息粗悯,客戶端用之前生成的隨機(jī)值解密服務(wù)端傳過(guò)來(lái)的信息,展現(xiàn)同欠。

59. assign 與 weak 的區(qū)別

weak 表明該屬性定義了一個(gè)非擁有關(guān)系样傍。用這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值铺遂,也不釋放舊值衫哥。用 weak 聲明的變量不用時(shí)會(huì)自動(dòng)清空,賦值為 nil襟锐,weak 可避免循環(huán)引用撤逢,一般用于 OC 對(duì)象和 delegate,自定義的 IBOutlet 控件屬性一般也使用 weak粮坞。

assign 主要用來(lái)基礎(chǔ)類型蚊荣,是指針賦值,不對(duì)引用計(jì)數(shù)操作捞蚂,使用完若不置為 nil妇押,就會(huì)造成野指針。

60. 如何使用 copy

1. NSString姓迅、NSArray敲霍、NSDictionary 經(jīng)常使用 copy俊马。copy 所表達(dá)的所屬關(guān)系與 strong 類似。然而設(shè)置方法并不保留新值肩杈,而是將其拷貝柴我。當(dāng)屬性類型是 NSString 時(shí)經(jīng)常用此特性來(lái)保護(hù)其封裝性,因?yàn)閭鬟f給 set 方法的新值有可能指向一個(gè) NSMutableString 類的實(shí)例扩然,這個(gè)類是 NSString 的子類艘儒,若是不拷貝字符串,那么設(shè)置完屬性后夫偶,字符串的值就可能會(huì)在對(duì)象不知情的情況下遭人更改界睁,所以使用 copy 可確保字符串不會(huì)無(wú)意間變動(dòng)。

用 @property 聲明 NSString兵拢、NSArray翻斟、NSDictionary 經(jīng)常使用 copy 關(guān)鍵字,是因?yàn)樗麄冇袑?duì)應(yīng)的可變類型:NSMutableString说铃、NSMutableArray访惜、NSMutableDictionary,他們之間可能進(jìn)行賦值操作腻扇,為確保對(duì)象中的字符串值不會(huì)無(wú)意間變動(dòng)债热,應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份。

2. block 使用 copy 是在 MRC 遺留下來(lái)的幼苛,在 MRC 中窒篱,方法內(nèi)部的 block 是存在棧區(qū)的,使用 copy 可以把它放在堆區(qū)蚓峦。為了能夠在 block 的聲明域外使用舌剂,所以要把 block 拷貝( copy )到堆,所以說(shuō)為了 block 屬性聲明和實(shí)際的操作一致暑椰,最好聲明為 copy霍转。

61. 下面的寫法會(huì)出什么問(wèn)題:

@property (atomic,copy) NSMutableArray *array;

1. 添加一汽、刪除避消、修改數(shù)組內(nèi)的元素時(shí),程序會(huì)找不到對(duì)應(yīng)的方法而崩潰召夹。因?yàn)?copy 就是復(fù)制一個(gè)不可變的 NSArray 對(duì)象岩喷。

2. 使用了 atomic 屬性,會(huì)嚴(yán)重影響性能监憎。

62. 如何讓自己的類用 copy 修飾符纱意?如何重寫帶 copy 關(guān)鍵字的 setter

若想令自己寫的對(duì)象具有拷貝功能,則需實(shí)現(xiàn) NSCopying 協(xié)議鲸阔。如果自定義的對(duì)象分為可變版本與不可變版本偷霉,那么就需要同時(shí)實(shí)現(xiàn) NSCopying 和 NSMutableCopying 協(xié)議:(1)首先遵循協(xié)議@interface CYLUser : NSObject@property (nonatomic, readonly, copy) NSString *name;

@property (nonatomic, readonly, assign) NSUInteger age;

- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;

+ (instancetype)userWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;

@end

(2)然后實(shí)現(xiàn)協(xié)議中規(guī)定的方法:

- (id)copyWithZone:(NSZone *)zone {

CYLUser *copy = [[[self class] allocWithZone:zone] initWithName:_name age:_age sex:_sex];

return copy;

}

重寫 copy 的 setter 方法時(shí)候,一定要調(diào)用一下傳入的對(duì)象的 copy 方法,然后在賦值給該 setter 的方法對(duì)應(yīng)的成員變量

63. 淺拷貝與深拷貝

(1)對(duì)非集合類對(duì)象的copy操作:

在非集合類對(duì)象中:對(duì) immutable 對(duì)象進(jìn)行 copy 操作迄委,是指針復(fù)制,mutableCopy 操作時(shí)內(nèi)容復(fù)制类少;對(duì) mutable 對(duì)象進(jìn)行 copy 和 mutableCopy 都是內(nèi)容復(fù)制

NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy

NSString *stringCopy = [string copy];

查看內(nèi)存叙身,會(huì)發(fā)現(xiàn) string、stringCopy 內(nèi)存地址都不一樣硫狞,說(shuō)明此時(shí)都是做內(nèi)容拷貝信轿、深拷貝

[string appendString:@"origion!"]

stringCopy 的值也不會(huì)因此改變,但是如果不使用 copy残吩,stringCopy 的值就會(huì)被改變财忽。

[immutableObject copy] // 淺復(fù)制

[immutableObject mutableCopy] //深復(fù)制

[mutableObject copy] //深復(fù)制

[mutableObject mutableCopy] //深復(fù)制

(2)在集合類對(duì)象中,對(duì) immutable 對(duì)象進(jìn)行 copy世剖,是指針復(fù)制定罢, mutableCopy 是內(nèi)容復(fù)制;對(duì) mutable 對(duì)象進(jìn)行 copy 和 mutableCopy 都是內(nèi)容復(fù)制旁瘫。但是:集合對(duì)象的內(nèi)容復(fù)制僅限于對(duì)象本身,對(duì)象元素仍然是指針復(fù)制琼蚯。

[immutableObject copy] // 淺復(fù)制

[immutableObject mutableCopy] //單層深復(fù)制

[mutableObject copy] //單層深復(fù)制

[mutableObject mutableCopy] //單層深復(fù)制

64. @property 的本質(zhì)是什么酬凳,ivar、getter遭庶、setter 是如何生成并添加到這個(gè)類中的

在普通 OC 對(duì)象中宁仔,@property 就是編譯器自動(dòng)幫我們生成一個(gè)成員變量(ivar)和它的 setter 和 getter 方法,它大概生成了五個(gè)東西:

1. objc_ivar_$類名$屬性名稱 該屬性的偏移量

2. setter 與 getter 方法對(duì)應(yīng)的實(shí)現(xiàn)函數(shù)

3. ivar_list 成員變量列表

4. method_list 方法列表

5. prop_list 屬性列表

也就是說(shuō)我們每次增加一個(gè)屬性峦睡,系統(tǒng)就會(huì)在成員變量列表中添加一個(gè)成員變量的描述翎苫,在方法列表中添加 setter 與 getter 方法的描述,在屬性列表中增加一個(gè)屬性描述榨了,然后計(jì)算該屬性在對(duì)象中的偏移量煎谍,然后生成 setter 與 getter 方法對(duì)應(yīng)的實(shí)現(xiàn),在 setter 方法中從偏移量開始復(fù)制龙屉,在 getter 中從偏移量開始取值呐粘,為了能夠讀取正確的自己數(shù),系統(tǒng)對(duì)對(duì)象偏移量的指針類型進(jìn)行了類型強(qiáng)轉(zhuǎn)转捕。

65. Runtime 如何實(shí)現(xiàn) weak 屬性

Runtime 對(duì)注冊(cè)的類會(huì)進(jìn)行布局作岖,對(duì)于 weak 對(duì)象會(huì)放入一個(gè) hash 表中。用 weak 指向的對(duì)象地址作為 key五芝,當(dāng)此對(duì)象的引用計(jì)數(shù)為0時(shí)會(huì) dealloc痘儡,進(jìn)而在這個(gè) weak 表中找到此對(duì)象地址為鍵的所有 weak 對(duì)象,從而設(shè)置為 nil枢步。

66. weak 屬性需要在 dealloc 中置 nil 么

不需要沉删,在 ARC 環(huán)境無(wú)論是強(qiáng)指針還是弱指針都無(wú)需在 dealloc 設(shè)置為 nil渐尿,ARC 會(huì)自動(dòng)幫我們處理

67. @synthesize 和 @dynamic 分別有什么作用

@property 有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是 @synthesize丑念,一個(gè)是 @dynamic涡戳。如果 @synthesize 和 @dynamic 都沒(méi)寫,那么默認(rèn)的就是 @syntheszie var = _var;

@synthesize 的語(yǔ)義是如果你沒(méi)有手動(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,然后你沒(méi)有提供 @setter 方法和 @getter 方法植榕,編譯的時(shí)候沒(méi)問(wèn)題再沧,但是當(dāng)程序運(yùn)行到 instance.var =someVar,由于缺 setter 方法會(huì)導(dǎo)致程序崩潰尊残;或者當(dāng)運(yùn)行到 someVar = var時(shí)炒瘸,由于缺 getter 方法同樣會(huì)導(dǎo)致崩潰。編譯時(shí)沒(méi)問(wèn)題寝衫,運(yùn)行時(shí)才執(zhí)行相應(yīng)的方法顷扩,這就是所謂的動(dòng)態(tài)綁定。

68. ARC 下慰毅,不顯示指定任何屬性關(guān)鍵字時(shí)隘截,默認(rèn)的關(guān)鍵字都有哪些?

對(duì)應(yīng)基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字時(shí) atomic汹胃,readwrite婶芭,assign;

對(duì)應(yīng)普通的 OC 對(duì)象是 atomic,readwrite着饥,strong

69. objc 中向一個(gè) nil 對(duì)象發(fā)送消息將會(huì)發(fā)生什么

在 OC 中向 nil 發(fā)送對(duì)象是完全有效的犀农,只是在運(yùn)行時(shí)不會(huì)有任何作用,OC 中 nil 是被當(dāng)做0定義的贱勃。也就是說(shuō) Runtime 要去獲取這個(gè) nil 的信息井赌,會(huì)去讀取內(nèi)存中0的位置,這肯定是不允許的贵扰,會(huì)返回 nil齿诉,0瓢喉,0.0等數(shù)據(jù)导狡。

70. objc 中向一個(gè)對(duì)象發(fā)送消息 [obj foo] 和 obj_msgSend() 函數(shù)之間有什么關(guān)系归斤?

該方法編譯之后就是 obj_msgSend() 函數(shù)調(diào)用,[obj foo] 就是在 objc 動(dòng)態(tài)編譯時(shí)舞丛,會(huì)被轉(zhuǎn)義為: objc_msgSend(obj, @selector(foo));

71. 什么時(shí)候會(huì)報(bào) unrecognized selector 的異常

當(dāng)調(diào)用該對(duì)象上某個(gè)方法耘子,而該對(duì)象上沒(méi)有實(shí)現(xiàn)這個(gè)方法的時(shí)候

72. 下面代碼會(huì)輸出什么

@implementation Son : Father

- (id)init

{

self = [super init];

if (self) {

NSLog(@"%@", NSStringFromClass([self class]));

NSLog(@"%@", NSStringFromClass([super class]));

}

return self;

}

@end

輸出都是 son 果漾。

因?yàn)樵?iOS 中,對(duì)方法的調(diào)用是通過(guò)發(fā)送消息來(lái)完成的谷誓。也就是說(shuō)使用 [self class] 時(shí)绒障,會(huì)使用 obj_msgSend(id theReceiver, SEL selector, ...)函數(shù)向 receiver 來(lái)發(fā)送消息。而使用 [super class] 時(shí)捍歪,會(huì)使用 obj_msgsendSuper(...) 函數(shù)向 receiver 來(lái)發(fā)送消息户辱。然而 obj_msgSend(...)和 obj_msgSendSuper(...) 中的 receiver 都是 self,這里的 self 也就是 son糙臼,所以輸出都是 son

73. iOS 中的 SEL 和 IMP 是什么

SEL 是類成員方法的指針庐镐,但不同于 C 語(yǔ)言中和函數(shù)指針,函數(shù)指針直接保存了方法的地址变逃,但 SEL 只是方法編號(hào)必逆;

IMP 是一個(gè)函數(shù)指針,保存了方法的地址揽乱。

SEL 和 IMP 關(guān)系:每一個(gè)繼承于 NSObject 的類都能自動(dòng)獲得 runtime 的支持名眉。在這樣一個(gè)類中,有一個(gè) isa 指針指向該類定義的數(shù)據(jù)結(jié)構(gòu)體凰棉,這個(gè)結(jié)構(gòu)體是由編譯器編譯時(shí)為類(需要繼承于 NSObject)創(chuàng)建的璧针,在這個(gè)結(jié)構(gòu)體中有包括了指向其父類類定義的指針以及 Dispatch table,它是一張 SEL 和 IMP 的對(duì)應(yīng)表渊啰。

也就是說(shuō)方法編號(hào) SEL 最后還是要通過(guò) Dispatch table 表尋找到對(duì)應(yīng)的 IMP,IMP 就是一個(gè)函數(shù)指針申屹,然后執(zhí)行這個(gè)方法绘证。

74. Runtime 如何通過(guò) selector 找到對(duì)應(yīng)的 IMP 地址(分別考慮類方法和實(shí)例方法)

每個(gè)類對(duì)象中都有一個(gè)方法列表,方法列表中記錄著方法的名稱哗讥、方法實(shí)現(xiàn)以及參數(shù)類型嚷那。其實(shí) selector 本質(zhì)就是方法名稱,通過(guò)這個(gè)方法名稱就可以在方法列表中找到對(duì)應(yīng)的方法實(shí)現(xiàn)杆煞。在尋找 IMP 地址時(shí)魏宽,Runtime 提供了兩種方法:

IMP class_getMethodImplementation(Class cls, SEL name);

IMP method_getImplementation(Method m)

而根據(jù)官方描述,第一種方法可能會(huì)更快一點(diǎn)决乎。對(duì)于第一種方法队询,類方法和實(shí)例方法實(shí)際上都是調(diào)用 class_getMethodImplementation() 來(lái)尋找 IMP 地址的,不同之處在于傳入的第一個(gè)參數(shù)不同:

類方法是 :class_getMethodImplementation(objc_getMetaClass("A"),@selector(methodName));

實(shí)例方法是:class_getMethodImplementation([A class],@selector(methodName));

selector 本質(zhì)就是方法的名稱构诚,通過(guò)該方法名稱蚌斩,即可在結(jié)構(gòu)體中找到相應(yīng)的實(shí)現(xiàn)。

struct objc_method {

SEL method_name

char *method_types

IMP method_imp

}

而對(duì)于第二種方法而言范嘱,傳入的參數(shù)只有 method送膳,區(qū)分類方法和實(shí)例方法在于封裝 method 的函數(shù)员魏,最后調(diào)用 IMP method_getImplementation(Method m) 獲取 IMP 地址。

75. 使用 Runtime Associate 方法關(guān)聯(lián)的對(duì)象叠聋,需要在主對(duì)象 dealloc 的時(shí)候釋放嗎撕阎?

在 ARC 下不需要;

在 MRC 下對(duì)于使用 retain 或 copy 策略的需要

76. objc 中的類方法和實(shí)例方法有什么本質(zhì)區(qū)別和聯(lián)系

類方法是屬于類對(duì)象的碌补,實(shí)例方法是屬于實(shí)例對(duì)象的虏束;

類方法只能通過(guò)類對(duì)象調(diào)用,實(shí)例方法只能通過(guò)實(shí)例對(duì)象調(diào)用脑慧;

類方法中的 self 是類對(duì)象魄眉,實(shí)例方法中的 self 是實(shí)例變量;

類方法中不能訪問(wèn)成員變量 闷袒,實(shí)例方法中可以訪問(wèn)成員變量坑律;

類方法中不能直接調(diào)用對(duì)象方法,實(shí)例方法中可以直接調(diào)用實(shí)例方法囊骤;

類方法可以調(diào)用其他的類方法晃择;

實(shí)例方法中也可以調(diào)用類方法(通過(guò)類名)。

77. _objc_msgForward函數(shù)是做什么的也物,直接調(diào)用它將會(huì)發(fā)生什么宫屠?

當(dāng)對(duì)象沒(méi)有實(shí)現(xiàn)某個(gè)方法,會(huì)調(diào)用這個(gè)函數(shù)進(jìn)行方法轉(zhuǎn)發(fā)滑蚯。(某方法對(duì)應(yīng)的 IMP 沒(méi)找到浪蹂,會(huì)返回這個(gè)函數(shù)的 IMP 去執(zhí)行)。

如果直接調(diào)用這個(gè)方法告材,就算實(shí)現(xiàn)了想調(diào)用的方法坤次,也不會(huì)被調(diào)用,會(huì)直接走消息轉(zhuǎn)發(fā)步驟斥赋。

78. 能否向編譯后得到的類中增加實(shí)例變量缰猴?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量?

因?yàn)榫幾g后的類已經(jīng)注冊(cè)在 Runtime 中疤剑,類結(jié)構(gòu)中的 objc_ivar_list 實(shí)例變量的鏈表和 instance_size 實(shí)例變量的內(nèi)存大小已經(jīng)確定滑绒,同時(shí) Runtime 會(huì)調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來(lái)處理 strong weak 引用,所以不能向存在的類中添加實(shí)例變量隘膘。

運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量的疑故,調(diào)用 class_addIvar 函數(shù)。但是得在調(diào)用 objc_allocateClassPair 之后棘幸,objc_registerClassPair 之前焰扳,原因同上。

79. runloop 和線程有什么關(guān)系

每一個(gè)線程中都有一個(gè) runloop,只用主線程的 runloop 吨悍,默認(rèn)是開啟的扫茅,其他線程的 runloop 默認(rèn)是關(guān)閉的,可以通過(guò) CFRunLoopRun() 函數(shù)開啟一個(gè)事件循環(huán)育瓜。

80. runloop 的 mode 作用是什么

mode 主要是用來(lái)指定事件在運(yùn)行循環(huán)中的優(yōu)先級(jí)

蘋果公開提供的 mode 有兩個(gè):kCFRunLoopDefaultMode 和 kCFRunLoopCommonModes葫隙。

如果我們把一個(gè) NSTimer 對(duì)象以 kCFRunLoopDefaultMode 添加到主運(yùn)行循環(huán)中的時(shí)候,當(dāng)一直有用戶事件處理的時(shí)候躏仇,NSTimer 將不再被調(diào)度恋脚。如果我們把一個(gè) NSTimer 對(duì)象以 kCFRunLoopCommonModes 添加到主運(yùn)行循環(huán)中的時(shí)候,當(dāng)一直有用戶事件處理的時(shí)候焰手,NSTimer 還能正常的調(diào)度糟描,互不影響。

81. 以 + scheduledTimerWithTimeInterval... 的方式觸發(fā)的 timer书妻,在滑動(dòng)頁(yè)面上的列表時(shí)船响,timer 會(huì)暫定回調(diào),為什么躲履?如何解決?

在主線程中以 +scheduledTimerWithTimeInterval... 的方式觸發(fā)的 timer 默認(rèn)是運(yùn)行在 NSDefaultRunLoopMode 模式下的,當(dāng)滑動(dòng)頁(yè)面上的列表時(shí),進(jìn)入了 UITrackingRunLoopMode 模式,這時(shí)候 timer 就會(huì)停止可以修改 timer 的運(yùn)行模式為 NSRunLoopCommonModes,這樣定時(shí)器就可以一直運(yùn)行了

82. 不手動(dòng)指定 autoreleasepool 的前提下见间,一個(gè) autorealese 對(duì)象在什么時(shí)刻釋放?(比如在一個(gè) vc 的 viewDidLoad 中創(chuàng)建)

在每次事件循環(huán)開始創(chuàng)建自動(dòng)釋放池,在每次事件結(jié)束銷毀自動(dòng)釋放池

以viewDidLoad方法為例,可以理解為在viewDidLoad方法開始執(zhí)行之前創(chuàng)建自動(dòng)釋放池,

在viewDidLoad方法執(zhí)行之后銷毀自動(dòng)釋放池

83. BAD_ACCESS 在什么情況下出現(xiàn)

1. 死循環(huán)工猜;

2. 訪問(wèn)了一個(gè)僵尸對(duì)象

84. 使用 block 時(shí)什么情況會(huì)發(fā)生循環(huán)引用

只要是一個(gè)對(duì)象對(duì)該 block 進(jìn)行了強(qiáng)引用米诉,在 block 內(nèi)部有直接使用到該對(duì)象

85. 在 block 內(nèi)如何修改 block 外部變量

通過(guò) __block 修改的外部變量,可以在 blcok 內(nèi)部修改篷帅。

block 不允許修改外部變量的值史侣。這里所說(shuō)的外部變量的值,指的是棧中指針的內(nèi)存地址魏身。__block 的作用就是只要觀察到該變量被 block 所持有抵窒,就將外部變量在棧中的內(nèi)存地址放到了堆中,進(jìn)而使得在 block 內(nèi)部也可以修改外部變量的值叠骑。

block 不允許修改外部變量的值,蘋果這樣設(shè)計(jì)削茁,應(yīng)該是考慮到了 block 也屬于函數(shù)的范疇宙枷,變量進(jìn)入 block,實(shí)際上就已經(jīng)改變了作用域茧跋。在幾個(gè)作用域之間進(jìn)行切換時(shí)慰丛,如果不加上這樣的限制,變量的可維護(hù)性將大大降低瘾杭。

86. GCD 的隊(duì)列分哪兩種類型

串行隊(duì)列和并行隊(duì)列

87. 如何用 GCD 同步若干個(gè)異步調(diào)用(如根據(jù)若干個(gè)url異步加載多張圖片诅病,然后在都下載完成后合成一張整圖)

創(chuàng)建異步隊(duì)列,創(chuàng)建 dispatch_group,通過(guò)組來(lái)執(zhí)行異步下載任務(wù):dispatch_group_async(queueGroup,aQueue,^{

NSLog(@“下載圖片”));

});

等到所有任務(wù)完成:dispatch_group_wait(queueGroup,DISPATCH_TIME_FOREVER);

合成圖片

88. dispatch_barrier_async 的作用是什么

dispatch_barrier_async 的作用是在并行隊(duì)列中贤笆,等待前面操作并行任務(wù)完成再執(zhí)行dispatch_barrier_async 中的任務(wù)蝇棉,若后面還有并行任務(wù),會(huì)開始執(zhí)行后續(xù)的并行任務(wù)芥永。

89. 蘋果為什么要廢棄 dispatch_get_current_queue

容易誤用造成死鎖

90. 下面代碼運(yùn)行結(jié)果

- (void)viewDidLoad

{

[super viewDidLoad];

NSLog(@"1");

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"2");

});

NSLog(@"3");

}

只輸出1篡殷,然后線程主線程死鎖

因?yàn)?dispatch_get_main_queue 得到的是一個(gè)串行隊(duì)列,串行隊(duì)列的特點(diǎn)是一次只調(diào)用一個(gè)任務(wù)埋涧,一個(gè)任務(wù)執(zhí)行完畢后再執(zhí)行下一個(gè)任務(wù)板辽。同步(sync)操作,它會(huì)阻塞當(dāng)前線程并等待 block 中的任務(wù)執(zhí)行完畢棘催,然后當(dāng)前線程才會(huì)繼續(xù)往下進(jìn)行劲弦。dispatch_sync 提交一個(gè)打印任務(wù) NSLog(@”2”) 到主線程關(guān)聯(lián)的串行隊(duì)列中,主線程關(guān)聯(lián)的串行任務(wù)到現(xiàn)在有一個(gè) viewDidLoad 任務(wù)醇坝,打印任務(wù) NSLog(@”2”) 排在 viewDidLoad 后面邑跪,隊(duì)列 FIFO(先進(jìn)先出)的原則,打印任務(wù) NSLog(@”2”)纲仍;想要得到執(zhí)行必須等到 viewDidLoad 執(zhí)行完畢后才能得到執(zhí)行呀袱,但 viewDidLoad 想要執(zhí)行完必須要等打印任務(wù) NSLog(@”2”) 執(zhí)行完畢,所以就卡死在這了郑叠。

91. addObserver:forKeyPath:options:context: 各個(gè)參數(shù)的作用分別是什么夜赵,observer 中需要實(shí)現(xiàn)哪個(gè)方法才能獲得 KVO 回調(diào)?

1. 觀察者乡革,負(fù)責(zé)處理監(jiān)聽事件的對(duì)象寇僧;

2. 觀察的屬性;

3. 觀察的選項(xiàng)沸版;

4. 上下文

- (void) observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void *)context;

92. IBOutlet 連出來(lái)的視圖屬性為什么可以被設(shè)置成 weak

使用 storyboard 創(chuàng)建的 VC嘁傀,那么會(huì)有一個(gè)叫 _topLevelObjectsToKeepAliveFromStoryboard 的私有數(shù)組強(qiáng)引用所有 toplevel 的對(duì)象,同時(shí) toplevel 對(duì)象強(qiáng)引用所有子對(duì)象视粮,那么 VC 沒(méi)必要再?gòu)?qiáng)引用 toplevel 對(duì)象的子對(duì)象细办。

93. IB中User Defined Runtime Attributes如何使用

它能夠通過(guò) KVC 的方式配置一些你在 interface builder 中不能配置的屬性。當(dāng)你希望在 IB 中作盡可能多得事情蕾殴,這個(gè)特性能夠幫助你編寫更加輕量級(jí)的 viewcontroller笑撞。

94. isMemberOfClass 和 isKindOfClass 聯(lián)系與區(qū)別

聯(lián)系:兩者都能檢測(cè)到一個(gè)對(duì)象是否是某個(gè)類的成員;

區(qū)別:isKindOfClass 不僅用來(lái)確定一個(gè)對(duì)象是否是一個(gè)類的成員钓觉,也可以用來(lái)確定一個(gè)對(duì)象是否是派生自該類的成員茴肥,而 isMemberOfClass 只能做到第一點(diǎn)。

比如 Class A 派生自 NSObject 類荡灾,ClassA *a = [ClassA alloc] init];? [a isKindOfClass:[NSObject class]] 可以檢查出 a 是否是 NSObject 派生類的成員瓤狐,但 isMemberOfClass 做不到瞬铸。

95. get 與 post 的區(qū)別

get 是向服務(wù)器索取數(shù)據(jù)的一種請(qǐng)求,post 是向服務(wù)器提交數(shù)據(jù)的一種請(qǐng)求础锐;

get 沒(méi)有請(qǐng)求體嗓节,post 有請(qǐng)求體;

get 使用 url 或 cookie 傳參郁稍,而 post 將數(shù)據(jù)放在 body 中赦政;

get 請(qǐng)求的數(shù)據(jù)會(huì)暴露在地址欄中,而 post 不會(huì)耀怜,所以 post 比 get 更安全恢着;

get 請(qǐng)求對(duì) url 長(zhǎng)度有限制,而 post 請(qǐng)求對(duì) url 理論上沒(méi)有限制财破,但實(shí)際上掰派,各個(gè)服務(wù)器會(huì)規(guī)定對(duì) post 提交數(shù)據(jù)大小進(jìn)行限制。

96. 設(shè)計(jì)模式是什么左痢,你知道哪些設(shè)計(jì)模式靡羡?

設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某種類型的事情俊性。

1. MVC 模式:模型包含了數(shù)據(jù)和邏輯的處理略步,控制器確保 model 與 view 的同步。

2. MVVM 模式:使用 Model View ViewModel 把模型定页、視圖趟薄、業(yè)務(wù)邏輯層進(jìn)行解耦和編寫。

3. 單例模式:通過(guò) static 關(guān)鍵字典徊,聲明全局變量杭煎,在整個(gè)進(jìn)程運(yùn)行期間只會(huì)被賦值一次。

4. 觀察者模式:KVO 是典型的通知模式卒落,觀察某個(gè)屬性的狀態(tài)羡铲,狀態(tài)發(fā)生變化時(shí)通知觀察者。

5. 委托模式:代理 + 協(xié)議的組合儡毕,實(shí)現(xiàn)1對(duì)1的反向傳值操作也切。

6. 工廠模式:通過(guò)一個(gè)類方法,批量的根據(jù)已有模板生產(chǎn)對(duì)象腰湾。

97. ?類變量的 @public贾费,@protected,@private檐盟,@package 聲明各有什么含義

@public 任何地方都能訪問(wèn);

@protected 該類和子類中訪問(wèn),是默認(rèn)的;

@private 只能在本類中訪問(wèn);

@package 本包內(nèi)使用,跨包不可以。

98. 什么是謂詞

謂詞就是通過(guò) NSPredicate 給定的邏輯條件作為約束條件押桃,完成對(duì)數(shù)據(jù)的篩選:

//定義謂詞對(duì)象,謂詞對(duì)象中包含了過(guò)濾條件(過(guò)濾條件比較多)

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age<%d",30];

//使用謂詞條件過(guò)濾數(shù)組中的元素,過(guò)濾之后返回查詢的結(jié)果

NSArray *array = [persons filteredArrayUsingPredicate:predicate];

99. APNS 原理

1. 應(yīng)用在通知中心注冊(cè)葵萎,由 iOS 系統(tǒng)向 APNS 請(qǐng)求返回設(shè)備令牌(Device Token)

2. 應(yīng)用程序接受到 Device Token 并發(fā)送給自己的后臺(tái)服務(wù)器

3. 服務(wù)器要把推送內(nèi)容和設(shè)備發(fā)送給 APNS

4. APNS 根據(jù) Device Token 找到設(shè)備,再由 iOS 根據(jù) APPID 把推送內(nèi)容展示

100. 描述下 SDWebImage 里面給 UIImageView 加載圖片的邏輯

SDWebImage 中為 UIImageView 提供了一個(gè)分類 UIImageView+WebCache.h。這個(gè)分類中有一個(gè)最常用的方法:sd_setImageWithURL:placeholderImage: 會(huì)在真實(shí)圖片出來(lái)前先顯示占位圖片羡忘,當(dāng)真實(shí)圖片被加載出來(lái)后再替換占位圖片谎痢。

加載過(guò)程大致如下:

首先會(huì)在 SDWebImageCache 中尋找圖片是否有對(duì)應(yīng)的緩存,它會(huì)以 url 作為數(shù)據(jù)索引先在內(nèi)存中尋找是否有對(duì)應(yīng)的緩存卷雕,如果緩存未找到就會(huì)利用通過(guò) MD5 處理過(guò)的 key 來(lái)繼續(xù)在磁盤中查詢對(duì)應(yīng)的數(shù)據(jù)节猿,如果找到了,就會(huì)把磁盤中的數(shù)據(jù)加載到內(nèi)存中漫雕,并將圖片顯示出來(lái)滨嘱,如果在內(nèi)存中和磁盤緩存中都沒(méi)有找到,就會(huì)向遠(yuǎn)程服務(wù)器發(fā)送請(qǐng)求浸间,開始下載圖片太雨,下載后的圖片會(huì)加載到緩存中,并寫入磁盤中魁蒜。整個(gè)獲取圖片的過(guò)程都是在子線程中執(zhí)行囊扳,獲取到圖片后回到主線程將圖片顯示出來(lái)。

原理:

從內(nèi)存中找到圖片兜看,找到直接使用锥咸;

從沙盒中找,找到使用细移,緩存到內(nèi)存中搏予;

從網(wǎng)絡(luò)上獲取,使用葫哗,緩存到內(nèi)存缔刹,緩存到沙盒。

iOS 面試題總結(jié)(二)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末劣针,一起剝皮案震驚了整個(gè)濱河市校镐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捺典,老刑警劉巖鸟廓,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異襟己,居然都是意外死亡引谜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門擎浴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)员咽,“玉大人,你說(shuō)我怎么就攤上這事贮预”词遥” “怎么了契讲?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)滑频。 經(jīng)常有香客問(wèn)我捡偏,道長(zhǎng),這世上最難降的妖魔是什么峡迷? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任银伟,我火速辦了婚禮,結(jié)果婚禮上绘搞,老公的妹妹穿的比我還像新娘彤避。我一直安慰自己,他們只是感情好看杭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布忠藤。 她就那樣靜靜地躺著,像睡著了一般楼雹。 火紅的嫁衣襯著肌膚如雪模孩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天贮缅,我揣著相機(jī)與錄音榨咐,去河邊找鬼。 笑死谴供,一個(gè)胖子當(dāng)著我的面吹牛块茁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桂肌,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼数焊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了崎场?” 一聲冷哼從身側(cè)響起佩耳,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谭跨,沒(méi)想到半個(gè)月后干厚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡螃宙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年蛮瞄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谆扎。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挂捅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出堂湖,到底是詐尸還是另有隱情闲先,我是刑警寧澤周瞎,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站饵蒂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酱讶。R本人自食惡果不足惜退盯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泻肯。 院中可真熱鬧渊迁,春花似錦、人聲如沸灶挟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稚铣。三九已至箱叁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惕医,已是汗流浹背耕漱。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抬伺,地道東北人螟够。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像峡钓,于是被迫代替她去往敵國(guó)和親妓笙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345