1、category和extension的區(qū)別
- category是分類,可以為類增加自定義方法
- extension是擴(kuò)展或者延展,能為類增加屬性、成員變量和方法
- 區(qū)別呢就是category不能增加屬性和成員變量想虎,而extension可以
- 實(shí)際項(xiàng)目中,category一般用于增加系統(tǒng)類的方法以方便使用叛拷,因?yàn)橛迷撓到y(tǒng)類的成員變量可以直接調(diào)用舌厨,還可以在內(nèi)部修改該變量,如NSString+MD5忿薇;extension一般用于擴(kuò)展自定義類的屬性或成員變量裙椭,經(jīng)常見的ViewController的.m文件中,我們?cè)黾拥乃接谐蓡T變量
- 如果非要給category添加成員變量也不是不可署浩,用runtime吧
objc_setAssociatedObject
2揉燃、define 和 const常量的區(qū)別
- define宏定義在預(yù)編譯階段就進(jìn)行替換;而const常量則在編譯階段被編譯
- define不會(huì)檢測(cè)數(shù)據(jù)類型只是替換筋栋,易導(dǎo)致錯(cuò)誤炊汤;const參與編譯,會(huì)檢測(cè)數(shù)據(jù)類型弊攘,較為安全
- define定義的常量在替換后運(yùn)行過程中會(huì)不斷地占用內(nèi)存抢腐,而const定義的常量存儲(chǔ)在數(shù)據(jù)段只有一份copy,效率更高
- define可以定義一些簡(jiǎn)單的函數(shù)如 #define sum(a) (a+a)襟交,const不可以迈倍;
3、static關(guān)鍵字的作用
一句概括捣域,限制變量和函數(shù)的作用域
- 函數(shù)(方法)體內(nèi) static 變量的作用范圍為該函數(shù)體啼染,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值焕梅;
- 在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問迹鹅,但不能被模塊外其它函數(shù)訪問;
- 在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用丘侠,這個(gè)函數(shù)的使用范圍被限制在聲明 它的模塊內(nèi)徒欣;
- 在類中的 static 成員變量屬于整個(gè)類所擁有逐样,對(duì)類的所有對(duì)象只有一份拷貝蜗字;
- 在類中的 static 成員函數(shù)屬于整個(gè)類所擁有打肝,這個(gè)函數(shù)不接收 this 指針,因而只能訪問類的static 成員變量
4挪捕、 堆和棧的區(qū)別
- 從數(shù)據(jù)存儲(chǔ)方面講粗梭,棧用于存放基本數(shù)據(jù)類型,對(duì)象的地址等级零;堆用于于存放對(duì)象類型断医,block的copy等
- 從分配空間大小看,棧分配的空間凶嗉汀鉴嗤;堆分配的空間大
- 從管理角度看,棧由編譯器自動(dòng)管理序调,無需我們手工控制醉锅;堆的釋放需要手動(dòng)控制,容易造成內(nèi)存泄漏发绢,因此為什么堆是需要內(nèi)存管理的硬耍。
5、OC的內(nèi)存管理機(jī)制
- ARC: Automatic Referance Count边酒,通過retainCount引用計(jì)數(shù)來判斷對(duì)象是否應(yīng)該被釋放经柴,每次 runloop 的時(shí)候,都會(huì)檢查自動(dòng)對(duì)象的 retainCount墩朦,如果retainCount 為 0坯认,說明該對(duì)象沒有地方需要繼續(xù)使用了,可以釋放掉了氓涣。系統(tǒng)會(huì)在編譯的時(shí)候鹃操,在代碼之間插入類似內(nèi)存管理的代碼,判斷retainCount是該+1 還是-1春哨,合理控制retainCount的計(jì)數(shù)
- Autorelease pool:自動(dòng)釋放池荆隘,程序中所有用autoreleased釋放的對(duì)象都會(huì)加入到Autorelease pool中,Autorelease pool會(huì)在線程結(jié)束的時(shí)候drain赴背,這時(shí)Autorelease pool中的所有對(duì)象都會(huì)被release一次
- 內(nèi)存管理的問題: 盡管ARC自動(dòng)引用計(jì)數(shù)幫助解決了MRC手動(dòng)管理內(nèi)存的問題椰拒,但是ARC下還是會(huì)存在內(nèi)存問題,如 1凰荚、循環(huán)引用會(huì)導(dǎo)致內(nèi)存泄漏 2燃观、Core Foundation和OC框架下的對(duì)象進(jìn)行橋接的時(shí)候,處理不當(dāng)也會(huì)引起內(nèi)存泄漏 3便瑟、Core Foundation框架下的對(duì)象對(duì)象不受ARC管理缆毁,需要開發(fā)者手動(dòng)釋放,存在安全隱患
6到涂、weak和assign的區(qū)別
- weak只能修飾引用類型脊框,而且是弱引用類型颁督,比如會(huì)出現(xiàn)循環(huán)引用的delegate代理屬性,delegate代理屬性也可以用assign修飾
- assign本質(zhì)上既可以修飾基本數(shù)據(jù)類型浇雹,也可以修飾引用類型沉御,但是實(shí)際使用只用來修飾基本數(shù)據(jù)類型。
- 不同點(diǎn):weak修飾引用類型昭灵,定義了一種“非擁有關(guān)系”吠裆,會(huì)在對(duì)象釋放之后,將對(duì)象置為nil烂完,OC中向nil對(duì)象發(fā)送消息不會(huì)引起崩潰试疙;而assign修飾引用類型,不會(huì)在對(duì)象釋放之后置為nil抠蚣,會(huì)造成野指針效斑;
7、使用automic一定是線程安全的嗎柱徙?
不是缓屠,automic原子屬性,只是在對(duì)象的setter和getter方法中是線程安全的护侮,例如self.arr = array 線程安全敌完,但是[self.arr objectAtIndex:3] 就不是線程安全的,需要的話只能另外加鎖
8羊初、 在有了自動(dòng)生成屬性變量之后滨溉,@synthesize還有什么用處
- 在沒有自動(dòng)生成屬性變量之前,我們必須用@systhesize才能生成對(duì)應(yīng)的setter和getter方法以及屬性變量
- 既然要用@synthesize长赞,證明此情況下不能自動(dòng)生成屬性變量晦攒,這些情況包含如下:
1、同時(shí)重寫setter和getter方法時(shí)
2得哆、只讀變量 重寫getter方法時(shí)
3脯颜、在 @protocol 中定義屬性
4、在category中定義屬性 - 以上方法都不會(huì)自動(dòng)生成屬性變量贩据,此時(shí)就需要@systhesize name = _name
9栋操、copy關(guān)鍵字什么時(shí)候用
- 對(duì)于不可變集合,使用copy只是對(duì)原對(duì)象的引用饱亮;對(duì)于可變集合矾芙,使用copy則是重新分配了一塊新的內(nèi)存,與原對(duì)象毫無關(guān)系
- 實(shí)際項(xiàng)目中近上,對(duì)于NSString剔宪、NSDictionary、NSArray都用copy,而可變集合NSMutableString葱绒、NSMutableArray使用copy感帅,進(jìn)行一次內(nèi)容的拷貝,內(nèi)容改變不會(huì)影響原對(duì)象的數(shù)據(jù)
- block使用copy哈街,只是MRC延續(xù)下來的習(xí)慣留瞳,在MRC中拒迅,block默認(rèn)創(chuàng)建在棧區(qū)骚秦,使用copy則可以把它放到堆區(qū);在ARC中寫不寫都行:對(duì)于 block 使用 copy 還是 strong 效果是一樣的璧微,但是建議寫上copy作箍,因?yàn)檫@樣顯示告知調(diào)用者“編譯器會(huì)自動(dòng)對(duì) block 進(jìn)行了 copy 操作”
10、對(duì)于不可變集合使用copy只是對(duì)原對(duì)象的引用前硫,那為什么不用strong呢
- 不可變集合如NSArray用copy只是增加對(duì)象的引用胞得,不會(huì)影響到對(duì)象的內(nèi)容,不論接收者是可變還是不可變屹电,持有的就是原對(duì)象的一個(gè)副本
- 如果換成是用strong阶剑,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象,如果這個(gè)可變對(duì)象在外部被修改了,那么會(huì)影響該屬性.
11、關(guān)于復(fù)制copy和mutableCopy
淺復(fù)制(shallow copy):在淺復(fù)制操作時(shí)危号,對(duì)于被復(fù)制對(duì)象的每一層都是指針復(fù)制牧愁。
深復(fù)制(one-level-deep copy):在深復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象外莲,至少有一層是深復(fù)制猪半。
完全復(fù)制(real-deep copy):在完全復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象的每一層都是對(duì)象復(fù)制偷线。
非集合類對(duì)象的copy與mutableCopy
[不可變對(duì)象 copy] // 淺復(fù)制
[不可變對(duì)象 mutableCopy] //深復(fù)制
[可變對(duì)象 copy] //深復(fù)制
[可變對(duì)象 mutableCopy] //深復(fù)制
- 集合類對(duì)象的copy與mutableCopy
[不可變對(duì)象 copy] // 淺復(fù)制
[不可變對(duì)象 mutableCopy] //單層深復(fù)制
[可變對(duì)象 copy] //單層深復(fù)制
[可變對(duì)象 mutableCopy] //單層深復(fù)制
這里需要注意的是集合對(duì)象的內(nèi)容復(fù)制僅限于對(duì)象本身磨确,對(duì)象元素仍然是指針復(fù)制
如:@property(nonatomic, copy)NSMutableArray *arr;這個(gè)寫法會(huì)出什么問題声邦?
1乏奥、添加、刪除亥曹、修改數(shù)組元素的時(shí)候英融,程序會(huì)因?yàn)檎也坏綄?duì)應(yīng)的方法而崩潰;
2、copy后返回的復(fù)制得到的不可變對(duì)象大脉,即NSArray寥闪,NSArray類型對(duì)象不能調(diào)用NSMutableArray類型對(duì)象的方法
原因:是因?yàn)閏opy就是復(fù)制一個(gè)不可變NSArray的對(duì)象,不能對(duì)NSArray類型的對(duì)象進(jìn)行添加刪除修改
12痕鳍、+(void)load; +(void)initialize;有什么用處?
- load方法
1、當(dāng)類對(duì)象被導(dǎo)入項(xiàng)目時(shí)笼呆,runtime會(huì)向每一個(gè)類對(duì)象發(fā)送load消息
2熊响、load方法在類或者分類被引入時(shí)僅調(diào)用一次;調(diào)用順序是父類诗赌、子類汗茄、分類
3、load方法不會(huì)被類自動(dòng)繼承
4铭若、因?yàn)閘oad方法是在導(dǎo)入類的時(shí)候就被調(diào)用且一次洪碳,所以在load方法中我們可以做一些runtime的操作或者希望只執(zhí)行一次的操作 - initiallize方法
在第一次使用這個(gè)類的時(shí)候被調(diào)用一次,也就是懶加載 - 總結(jié)
1叼屠、 在OC中瞳腌,runtime都會(huì)自動(dòng)調(diào)用每個(gè)類的這兩個(gè)方法
2、load是在類初始加載的時(shí)候調(diào)用镜雨;initiallize是在第一次調(diào)用該類方法或者實(shí)例方法的時(shí)候被調(diào)用
3嫂侍、共同點(diǎn): 只有在實(shí)現(xiàn)的前提下才會(huì)被調(diào)用; 只會(huì)調(diào)用一次\
13荚坞、addObserVer: keyPath: options: context: ,KVO的實(shí)現(xiàn)原理
- observer挑宠,觀察者;keyPath颓影,要觀察的屬性或成員變量各淀;options:觀察值的選項(xiàng)(新值、舊值還是都觀察)瞭空;context傳入的參數(shù)揪阿; KVO是基于runtime實(shí)現(xiàn)的
- 在類的某個(gè)屬性被第一次觀察的時(shí)候,系統(tǒng)會(huì)在runtime時(shí)期動(dòng)態(tài)的創(chuàng)建一個(gè)該類的派生類如NSKVONotifing_Persion咆畏,在該派生類中南捂,會(huì)重寫被觀察屬性的setter方法,該setter方法中旧找,派生類實(shí)現(xiàn)了真正的通知機(jī)制
- OC中每個(gè)類對(duì)象都會(huì)有一個(gè)isa指針指向該類溺健,當(dāng)該類的屬性第一次被觀察,系統(tǒng)會(huì)將該類的isa指針去指向派生類钮蛛,從而屬性值改變調(diào)用setter的時(shí)候會(huì)調(diào)用派生類的setter方法
- 鍵值觀察通知依賴于NSObject 的兩個(gè)方法: willChangeValueForKey: 和 didChangevlueForKey:鞭缭;在一個(gè)被觀察屬性發(fā)生改變之前, willChangeValueForKey: 一定會(huì)被調(diào)用魏颓,這就 會(huì)記錄舊的值岭辣。而當(dāng)改變發(fā)生后,didChangeValueForKey: 會(huì)被調(diào)用甸饱,繼而 observeValueForKey:ofObject:change:context: 也會(huì)被調(diào)用沦童。
14仑濒、 什么是block
- block是一個(gè)匿名函數(shù),也是一個(gè)代碼塊偷遗,本質(zhì)上也是OC中的對(duì)象墩瞳,底層也是結(jié)構(gòu)體
- block用于回調(diào),是一個(gè)不需要立即執(zhí)行的代碼塊氏豌,可以控制執(zhí)行時(shí)機(jī)
- block屬性用copy修飾喉酌,使用中要注意避免循環(huán)引用
+block的注意點(diǎn):
1、block內(nèi)部使用外部指針會(huì)造成循環(huán)引用泵喘,需要用__weak修飾外部指針泪电;
__weak typeOf(self) weakSelf = self;
2、block內(nèi)部如果調(diào)用了延時(shí)函數(shù)還是用弱指針會(huì)取不到該指針涣旨,因?yàn)橐呀?jīng)被銷毀了歪架,需要在block內(nèi)再將弱指針強(qiáng)引用一下
__strong typeOf(self) strongSelf = weakSelf;
3股冗、如果需要在block內(nèi)部修改外部棧區(qū)變量霹陡,需要用__block修飾外部變量。
15止状、block要用copy修飾,還是用strong
block本身是像對(duì)象一樣可以retain烹棉,和release。但是怯疤,block在創(chuàng)建的時(shí)候浆洗,它的內(nèi)存是分配在棧(stack)上,而不是在堆(heap)上集峦。他本身的作于域是屬于創(chuàng)建時(shí)候的作用域伏社,一旦在創(chuàng)建時(shí)候的作用域外面調(diào)用block將導(dǎo)致程序崩潰。
使用retain也可以塔淤,但是block的retain行為默認(rèn)是用copy的行為實(shí)現(xiàn)的摘昌,
因?yàn)閎lock變量默認(rèn)是聲明為棧變量的,為了能夠在block的聲明域外使用高蜂,所以要把block拷貝(copy)到堆聪黎,所以說為了block屬性聲明和實(shí)際的操作一致,最好聲明為copy备恤。
16稿饰、KVC 和KVO
KVC,即NSKeyValueCoding兼職編碼, 一種非正式的protocol露泊,提供了一種機(jī)制來間接訪問對(duì)象的屬性喉镰,而不是通過setter和getter方法 ,以key為例惭笑,當(dāng)然還有keyPath
1侣姆、在使用KVC去訪問屬性變量的時(shí)候,系統(tǒng)首先是查找該類的setter和getter方法;
2铺敌、如果沒有找到setter和getter方法汇歹,就會(huì)找key對(duì)應(yīng)的帶下劃線的屬性或成員變量;
3偿凭、如果沒有帶下劃線的屬性或成員變量产弹,就找不帶下劃線的屬性或成員變量
4、如果不帶下劃線的屬性和成員變量也沒有弯囊,就會(huì)執(zhí)行setValue:(id)value forUndefinedKey或者valueForUndefinedKey痰哨,如果該類沒有實(shí)現(xiàn)對(duì)應(yīng)的方法,就會(huì)導(dǎo)致崩潰KVO匾嘱,KVC是KVO的基礎(chǔ)斤斧,通過鍵值路徑keypath觀察對(duì)象的某個(gè)屬性或成員變量,在KVC賦值事件發(fā)生的時(shí)候霎烙,KVO的觀察者就會(huì)發(fā)起內(nèi)部的通知機(jī)制撬讽,詳細(xì)看編號(hào)13
17、設(shè)計(jì)模式是什么悬垃? 你知道哪些設(shè)計(jì)模式游昼,并簡(jiǎn)要敘述
- 設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型的事情
1尝蠕、MVC模式: Model View Control烘豌,把模型 視圖 控制器層進(jìn)行解耦和編寫;
2看彼、MVVM模式:Model View ViewModel廊佩,把模型 視圖 業(yè)務(wù)邏輯 層進(jìn)行解耦和編寫;
3靖榕、單例模式:通過static關(guān)鍵詞标锄,聲明全局變量。在整個(gè)進(jìn)程運(yùn)行期間只會(huì)被賦值一次序矩;
4鸯绿、觀察者模式KVO: KVO是典型的通知模式,觀察某個(gè)屬性的狀態(tài)簸淀,狀態(tài)發(fā)生變化時(shí)通知觀察者瓶蝴;
5、委托模式:代理+協(xié)議的組合租幕,實(shí)現(xiàn)一對(duì)一的反向傳值操作舷手;
6、工廠模式:通過一個(gè)類方法劲绪,批量的根據(jù)已有模板生產(chǎn)對(duì)象男窟。
18盆赤、#import 、 #include 歉眷、 @class有什么區(qū)別 牺六? #import<> 和#import" " 有什么區(qū)別
-
import是OC導(dǎo)入頭文件的關(guān)鍵字,#include是C\C++導(dǎo)入頭文件的關(guān)鍵字汗捡;使用#import導(dǎo)入頭文件會(huì)自動(dòng)只導(dǎo)入一次淑际,不會(huì)重復(fù)導(dǎo)入
- @class是OC中告訴編輯器某個(gè)類的聲明,不會(huì)立即去查看這個(gè)類的實(shí)現(xiàn)扇住,只有執(zhí)行時(shí)才回去查看類的實(shí)現(xiàn)春缕,可以解決頭文件的相互包含
-
import<> 用于導(dǎo)入系統(tǒng)頭文件, #import "" 用于導(dǎo)入自定義類頭文件
19艘蹋、@property的本質(zhì)是什么锄贼?ivar、getter女阀、setter是如何生成并添加到這個(gè)類中的
- @property的本質(zhì) = ivar + getter + setter宅荤,“屬性”有兩大概念:ivar(實(shí)例變量) 、 getter+setter(存取方法)
- “屬性”(property)作為OC的一項(xiàng)特性强品,主要的作用就在于封裝對(duì)象的數(shù)據(jù)膘侮。OC對(duì)象通常會(huì)把其所需要的數(shù)據(jù)保存為各種實(shí)例變量屈糊。實(shí)例變量一般通過存取方法來訪問的榛,其中,“獲取方法”(getter)用于讀取變量值逻锐,“設(shè)置方法”(setter)用于寫入變量值夫晌。
20、屬性關(guān)鍵字assign昧诱、retain晓淀、copy、nonatomic各是什么作用盏档,在哪種情況下使用凶掰?
- assign是賦值特性,setter方法將傳入?yún)?shù)賦值給實(shí)例變量蜈亩;僅設(shè)置變量時(shí)懦窘,assign用于基本數(shù)據(jù)類型;
- retain(MRC)/strong(ARC)表示持有特性稚配,setter方法將傳入?yún)?shù)先保留畅涂,再賦值,傳入?yún)?shù)的retainCount會(huì)加1道川;
- copy表示拷貝特性午衰。setter方法會(huì)將傳入對(duì)象復(fù)制一份立宜,需要完全一份新的變量時(shí)
- nonatomic表示非原子特性,決定編譯器生成的setter和getter方法是否是原子操作臊岸,atomic表示多線程安全橙数,一般使用nonatomic,效率高帅戒。
21商模、如何讓自己的類用copy修飾符?如何重寫帶copy關(guān)鍵字的setter蜘澜?
- 需要實(shí)現(xiàn)NSCoping協(xié)議施流,如果自定義的對(duì)象分為可變和不可變版本,那么就要同時(shí)實(shí)現(xiàn)NSCoping和NSMutableCoping協(xié)議鄙信。
具體步驟:
1瞪醋、遵循NSCoping協(xié)議
2、實(shí)現(xiàn)協(xié)議方法copyWithZone
22装诡、ViewController的生命周期
- 按照?qǐng)?zhí)行順序排列
1银受、initWithCoder: 通過nib文件初始化時(shí)觸發(fā)
2、awakeFromNib:nib文件被加載的時(shí)候鸦采,會(huì)發(fā)生一個(gè)awakeFromNib的消息到nib文件中的每個(gè)對(duì)象
3宾巍、loadView: 開始加載試圖控制器自導(dǎo)的view
4、viewDidLoad:試圖控制器的view加載完成
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玄叠、viewWillDisappear:試圖控制器的view已經(jīng)從window上消失
23古徒、為什么NSArray、NSDictionary读恃、NSString經(jīng)常使用copy關(guān)鍵字
- 是因?yàn)樗麄冇袑?duì)應(yīng)的可變類型NSMutableArray隧膘、NSMutableDictionary、NSMutableString寺惫,可變與不可變之間可能會(huì)進(jìn)行賦值操作疹吃,如果不可變賦值給可變對(duì)象,那可變對(duì)象修改數(shù)據(jù)可能會(huì)影響到原來的不可變對(duì)象肌蜻,如果用copy的話互墓,不管怎么賦值,都是原對(duì)象copy了一份蒋搜,被賦值對(duì)象作何修改不會(huì)影響到原對(duì)象
24篡撵、談一下OC的反射機(jī)制
- class反射
1判莉、通過類名的字符串形式實(shí)例化對(duì)象
Class class = NSClassFromString(@"Person");
Person *person = [[class alloc]init];
person.name = @"lisa";
2、將類名變?yōu)樽址?/p>
NSString *personStr = NSStringFromClass([Person class]);
- SEL反射
1育谬、通過方法的字符串實(shí)例化方法
SEL selector = NSSelectorFromString(@"testSel");
2券盅、方法變成字符串
SEL sel = @selector(testSel);
NSString *str = NSStringFromSelector(sel);
25、什么是謂詞膛檀?
- 謂詞就是通過NSPredicate給定的邏輯條件作為約束條件锰镀,完成對(duì)數(shù)據(jù)的篩選
NSArray *persons = @[person1,person2,person3];
//定義謂詞, 設(shè)置過濾條件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age>%d",30];
//通過謂詞條件過濾數(shù)組中的元素咖刃,過濾之后返回查詢結(jié)果
NSArray *arr = [persons filteredArrayUsingPredicate:predicate];
26泳炉、isa指針問題
- isa: 是一個(gè)Class類型的指針,每個(gè)實(shí)例對(duì)象都有一個(gè)isa指針嚎杨,指向其所對(duì)應(yīng)的類花鹅,而類Class里也有個(gè)isa指針,指向meteClass(元類)枫浙。元類保存了類方法的列表刨肃。當(dāng)類方法被調(diào)用時(shí),會(huì)先從本身查找類方法的實(shí)現(xiàn)箩帚,如果沒有真友,元類會(huì)向它父類查找該方法。需要注意的是紧帕,元類也是類盔然,他也是對(duì)象。元類也有isa指針焕参,指向的是根元類(root meteClass)轻纪,根元類的isa指針指向本身,這樣形成了一個(gè)封閉的內(nèi)循環(huán)叠纷。
27、如何修改一個(gè)類的私有屬性
- KVC: setValue:屬性值 forKey:屬性名
- runtime: object_setIvar(self, 屬性名, 屬性值)
28潦嘶、isKindOfClass isMemberOfClass selector
- isKindOfClass: 判斷某個(gè)對(duì)象是否屬于該類型或者繼承自該類型
- isMemberOfClass: 判斷某個(gè)對(duì)象是否是該類型
- selector 通過方法名獲取該函數(shù)在內(nèi)存中的入口
29涩嚣、delegate和NSNotification的區(qū)別
- 兩者都用于傳遞消息,不同之處在于一個(gè)是一對(duì)一的掂僵,一個(gè)是一對(duì)多的
- Notification需要維護(hù)一個(gè)數(shù)組航厚,實(shí)現(xiàn)一對(duì)多的消息的轉(zhuǎn)發(fā)
- delegate需要兩者之間建立聯(lián)系,不然沒法調(diào)用代理的方法锰蓬;Notification不需要兩者建立聯(lián)系
30幔睬、iOS中常用的數(shù)據(jù)存儲(chǔ)方式
數(shù)據(jù)存儲(chǔ)有四種方案:NSUserDefault、KeyChain芹扭、file(文件存儲(chǔ))麻顶、DB(數(shù)據(jù)庫存儲(chǔ))
file包括:plist赦抖、Archive(歸檔)
DB包括:SQLite、FMDB辅肾、CoreData
31队萤、iOS的沙盒目錄結(jié)構(gòu)
- Application:存放程序源文件
- Documents:常用目錄,iCloud備份目錄矫钓,存放數(shù)據(jù)要尔。
- Library :
1、Caches:存放體積大又不需要備份的數(shù)據(jù)新娜。(常用的緩存路徑)
2赵辕、Preference:設(shè)置目錄,iCloud會(huì)備份設(shè)置信息 - tmp:存放臨時(shí)文件概龄,不會(huì)備份匆帚,而且這個(gè)文件下的數(shù)據(jù)有可能隨時(shí)被清除。
32旁钧、iOS中的幾種多線程實(shí)現(xiàn)方案
- pthread:適用于Unix吸重、Linux、Windos等系統(tǒng)歪今,跨平臺(tái)可移植嚎幸,線程生命周期由程序員管理
- NSThread:面向?qū)ο螅芍苯硬僮骶€程對(duì)象寄猩,線程生命周期由程序員管理
- GCD: 充分利用設(shè)備的多核嫉晶,基于C語言底層的多線程API,線程生命周期系統(tǒng)自動(dòng)管理
- NSOperation:基于GCD田篇,更加面向?qū)ο筇娣希€程生命周期系統(tǒng)自動(dòng)管理
33、簡(jiǎn)明扼要的說一下runloop
runloop也叫做運(yùn)行循環(huán)泊柬,循環(huán)內(nèi)部處理著各種事務(wù)椎镣。一個(gè)線程對(duì)應(yīng)一個(gè)runloop,基本作用就是保持線程的持續(xù)運(yùn)行兽赁,處理線程中的各種事件状答。通過runloop,可以讓線程在有事件的時(shí)候處理事件刀崖,沒事件的時(shí)候休息惊科,可以節(jié)省cpu資源,提高運(yùn)行效率亮钦;
34馆截、什么是runtime
- runtime是OC語言的重要特性,叫做運(yùn)行時(shí)蜂莉,是一套底層的C語言的API蜡娶,平時(shí)編寫的OC代碼混卵,底層都是用他來實(shí)現(xiàn)的
35、Runtime實(shí)現(xiàn)的機(jī)制是什么翎蹈?怎么用淮菠,一般用于干什么?
- Runtime是iOS運(yùn)行時(shí)特性實(shí)現(xiàn)的基礎(chǔ)
1荤堪、使用時(shí)需導(dǎo)入頭文件 <objc/message.h> <objc/runtime.h>
2合陵、Runtime 運(yùn)行時(shí)機(jī)制,它是一套C語言庫澄阳。
3拥知、實(shí)際上我們編寫的所有OC代碼,最終都是轉(zhuǎn)成了runtime庫的東西碎赢。比如:1)OC中的類轉(zhuǎn)成了Runtime庫里的結(jié)構(gòu)體等數(shù)據(jù)類型 2)方法轉(zhuǎn)成了Runtime庫里C語言函數(shù) 3)方法的調(diào)用都是Runtime庫里通過objc_msgSend低剔,OC是動(dòng)態(tài)語言,每個(gè)方法在運(yùn)行時(shí)都會(huì)動(dòng)態(tài)轉(zhuǎn)化為消息發(fā)送肮塞,objc_msgSend(receiver, selector)
4襟齿、由此,可以說Runtime是OC的底層實(shí)現(xiàn)枕赵,是OC的幕后執(zhí)行者
+Runtime能做什么
- Runtime庫里包含了和類猜欺、成員變量、方法相關(guān)的API拷窜。比如:
1)獲取類中的所有成員變量
2)獲取類中的所有方法
3)為類動(dòng)態(tài)添加成員變量
4)為類動(dòng)態(tài)添加新的方法 - 什么是 Method Swizzle(黑魔法)开皿,什么情況下會(huì)使用?
1)在沒有一個(gè)類的方法的實(shí)現(xiàn)源碼的函數(shù)篮昧,想要修改它赋荆,除了通過繼承和category之外,還可以通過Method Swizzle
2)每個(gè)類都有一個(gè)方法列表懊昨,存放著selector的名字和方法實(shí)現(xiàn)的映射關(guān)系窄潭。IMP就類似于函數(shù)指針,指向方法的真正實(shí)現(xiàn)
3)在OC中調(diào)用一個(gè)方法疚颊,其實(shí)是向一個(gè)對(duì)象發(fā)送消息狈孔,查找消息的唯一依據(jù)是selector的名字。利用OC的動(dòng)態(tài)特性材义,可以實(shí)現(xiàn)在運(yùn)行時(shí)偷換selector對(duì)應(yīng)的方法實(shí)現(xiàn)。
//根據(jù) SEL 獲取到 Method
Method method1 = class_getClassMethod(self, @selector(function1));
Method method2 = class_getClassMethod(self, @selector(function2));
//根據(jù)SEL 獲取到 方法的實(shí)現(xiàn) IMP
IMP imp = class_getMethodImplementation(self, @selector(function3));
//修改方法Method 的實(shí)現(xiàn)IMP
method_setImplementation(method1, imp);
//為類添加方法
class_addMethod(self, @selector(function3), imp, "");
//交換兩個(gè)方法的實(shí)現(xiàn)嫁赏,傳入的是Method其掂,實(shí)際交換的是IMP
method_exchangeImplementations(method1, method2);
IMP imp2 = class_getMethodImplementation(self, @selector(function2));
//替換SEL對(duì)應(yīng)的實(shí)現(xiàn)IMP
class_replaceMethod(self, @selector(function3), imp2, "");
- _objc_msgForward 函數(shù)是做什么的
_objc_msgForward是 IMP 類型呼巷,用于消息轉(zhuǎn)發(fā)的:當(dāng)向一個(gè)對(duì)象發(fā)送一條消息碍彭,但它并沒有實(shí)現(xiàn)的時(shí)候用踩,_objc_msgForward會(huì)嘗試做消息轉(zhuǎn)發(fā)婉称。
36、HTTP協(xié)議中 POST 方法和 GET 方法有那些區(qū)別?
- GET方法用于請(qǐng)求數(shù)據(jù)贤牛,POST方法用于提交數(shù)據(jù)惋鹅;
- GET請(qǐng)求,參數(shù)拼接在訪問路徑url上殉簸,安全性不高闰集;POST請(qǐng)求參數(shù)放在請(qǐng)求體body里面,參數(shù)與訪問路徑url分開般卑,較為安全武鲁;
- GET請(qǐng)求,訪問路徑url有長(zhǎng)度限制蝠检,不超過255個(gè)字節(jié)沐鼠,而POST請(qǐng)求訪問路徑長(zhǎng)度沒有限制
37、簡(jiǎn)述APNS發(fā)送系統(tǒng)消息即推送的機(jī)制
1)應(yīng)用程序在通知中心注冊(cè)推送叹谁,由iOS系統(tǒng)向APNS請(qǐng)求返回設(shè)備令牌device Token饲梭;
2)應(yīng)用程序接收到APNS返回的設(shè)備令牌device Token,發(fā)送給自己的服務(wù)器焰檩;
3)服務(wù)器把需要推送的內(nèi)容和設(shè)備令牌device Token憔涉,發(fā)送給APNS
4)APNS通過device Token找到要發(fā)送的設(shè)備,iOS系統(tǒng)根據(jù)APPID把推送內(nèi)容展示
38锅尘、方法和選擇器(Selector)的區(qū)別
選擇器Selector是方法的名字监氢,通過它可以找到方法;
方法是相對(duì)對(duì)象來說的藤违,包含方法的名字和實(shí)現(xiàn)浪腐。
39、[self class] 和 [super class]輸出同樣的結(jié)果-當(dāng)前類Son顿乒,[super class]輸出的不是父類Father议街,為什么?
#import "Father.h"
@interface Son : Father
@property(nonatomic,assign)int age;
@end
@implementation Son
-(instancetype)init{
if (self = [super init]) {
NSLog(@"[self class]=====%@",[self class]); //Son
NSLog(@"[super class]=====%@",[super class]); //Son
}
return self;
}
@end
self 表示當(dāng)前這個(gè)類的對(duì)象璧榄,而 super 是一個(gè)編譯器標(biāo)示符特漩,和 self 指向同一個(gè)消息接受者。在本例中骨杂,無論是[self class]還是[super class]涂身,接受消息者都是Son對(duì)象,但super與self不同的是搓蚪,self調(diào)用class方法時(shí)蛤售,是在子類Son中查找方法,而super調(diào)用class方法時(shí),是在父類Father中查找方法悴能。
當(dāng)調(diào)用[self class]方法時(shí)揣钦,會(huì)轉(zhuǎn)化為objc_msgSend函數(shù),這個(gè)函數(shù)定義如下:
id objc_msgSend(id self, SEL op, ...)
這時(shí)會(huì)從當(dāng)前Son類的方法列表中查找漠酿,如果沒有冯凹,就到Father類查找,還是沒有炒嘲,最后在NSObject類查找到宇姚。我們可以從NSObject.mm文件中看到- (Class)class的實(shí)現(xiàn):
- (Class)class {
return object_getClass(self);
}
所以NSLog(@"%@", NSStringFromClass([self class]));會(huì)輸出Son。
當(dāng)調(diào)用[super class]方法時(shí)摸吠,會(huì)轉(zhuǎn)化為objc_msgSendSuper空凸,這個(gè)函數(shù)定義如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
objc_msgSendSuper函數(shù)第一個(gè)參數(shù)super的數(shù)據(jù)類型是一個(gè)指向objc_super的結(jié)構(gòu)體,從message.h文件中查看它的定義:
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained Class class;
#else
__unsafe_unretained Class super_class;
#endif
/* super_class is the first class to search */
};
#endif
結(jié)構(gòu)體包含兩個(gè)成員寸痢,第一個(gè)是receiver呀洲,表示某個(gè)類的實(shí)例。第二個(gè)是super_class表示當(dāng)前類的父類啼止。
這時(shí)首先會(huì)構(gòu)造出objc_super結(jié)構(gòu)體道逗,這個(gè)結(jié)構(gòu)體第一個(gè)成員是self,第二個(gè)成員是(id)class_getSuperclass(objc_getClass("Son"))献烦,實(shí)際上該函數(shù)會(huì)輸出Father滓窍。然后在Father類查找class方法,查找不到巩那,最后在NSObject查到吏夯。此時(shí),內(nèi)部使用objc_msgSend(objc_super->receiver, @selector(class))去調(diào)用即横,與[self class]調(diào)用相同噪生,所以結(jié)果還是Son。
第三方框架
- AFNetworking 底層原理分析
AFNetworking主要是對(duì)NSURLSession和NSURLConnection(iOS9.0廢棄)的封裝,其中主要有以下類:
1). AFHTTPRequestOperationManager:內(nèi)部封裝的是 NSURLConnection, 負(fù)責(zé)發(fā)送網(wǎng)絡(luò)請(qǐng)求, 使用最多的一個(gè)類东囚。(3.0廢棄)
2). AFHTTPSessionManager:內(nèi)部封裝是 NSURLSession, 負(fù)責(zé)發(fā)送網(wǎng)絡(luò)請(qǐng)求,使用最多的一個(gè)類跺嗽。
3). AFNetworkReachabilityManager:實(shí)時(shí)監(jiān)測(cè)網(wǎng)絡(luò)狀態(tài)的工具類。當(dāng)前的網(wǎng)絡(luò)環(huán)境發(fā)生改變之后,這個(gè)工具類就可以檢測(cè)到页藻。
4). AFSecurityPolicy:網(wǎng)絡(luò)安全的工具類, 主要是針對(duì) HTTPS 服務(wù)桨嫁。
5). AFURLRequestSerialization:序列化工具類,基類。上傳的數(shù)據(jù)轉(zhuǎn)換成JSON格式
(AFJSONRequestSerializer).使用不多份帐。
6). AFURLResponseSerialization:反序列化工具類;基類.使用比較多:
7). AFJSONResponseSerializer; JSON解析器,默認(rèn)的解析器.
8). AFHTTPResponseSerializer; 萬能解析器; JSON和XML之外的數(shù)據(jù)類型,直接返回二進(jìn)制數(shù)據(jù).對(duì)服務(wù)器返回的數(shù)據(jù)不做任何處理.
9). AFXMLParserResponseSerializer; XML解析器;
- 描述下SDWebImage里面給UIImageView加載圖片的邏輯
內(nèi)存 ——> 沙盒 ——> 網(wǎng)絡(luò)
SDWebImage 中為 UIImageView 提供了一個(gè)分類UIImageView+WebCache.h, 這個(gè)分類中有一個(gè)最常用的接口sd_setImageWithURL:placeholderImage:璃吧,會(huì)在真實(shí)圖片出現(xiàn)前會(huì)先顯示占位圖片,當(dāng)真實(shí)圖片被加載出來后再替換占位圖片废境。
加載圖片的過程大致如下:
1.首先會(huì)在 SDWebImageCache 中尋找圖片是否有對(duì)應(yīng)的緩存, 它會(huì)以u(píng)rl 作為數(shù)據(jù)的索引先在內(nèi)存中尋找是否有對(duì)應(yīng)的緩存
2.如果緩存未找到就會(huì)利用通過MD5處理過的key來繼續(xù)在磁盤中查詢對(duì)應(yīng)的數(shù)據(jù), 如果找到了, 就會(huì)把磁盤中的數(shù)據(jù)加載到內(nèi)存中肚逸,并將圖片顯示出來
3.如果在內(nèi)存和磁盤緩存中都沒有找到爷辙,就會(huì)向遠(yuǎn)程服務(wù)器發(fā)送請(qǐng)求彬坏,開始下載圖片
4.下載后的圖片會(huì)加入緩存中朦促,并寫入磁盤中
5.整個(gè)獲取圖片的過程都是在子線程中執(zhí)行,獲取到圖片后回到主線程將圖片顯示出來
SDWebImage原理:
調(diào)用類別的方法:
- 從內(nèi)存(字典)中找圖片(當(dāng)這個(gè)圖片在本次使用程序的過程中已經(jīng)被加載過)栓始,找到直接使用务冕。
- 從沙盒中找(當(dāng)這個(gè)圖片在之前使用程序的過程中被加載過),找到使用幻赚,緩存到內(nèi)存中禀忆。
- 從網(wǎng)絡(luò)上獲取,使用落恼,緩存到內(nèi)存箩退,緩存到沙盒。
待續(xù)佳谦。戴涝。。钻蔑。啥刻。。