1、NSSet與NSArray的區(qū)別
NSArray在內(nèi)存中是連續(xù)的,NSSet不連續(xù)
NSSet效率更高,內(nèi)部使用hash查找;NSArray查找需要遍歷
NSSet通過anyObject訪問元素,NSArray通過下標訪問
2、NSHashTable與NSMapTable
NSHashTable是NSSet的通用版本,對元素弱引用,可變類型;可以在訪問成員時copy
NSMapTable是NSDictionary的通用版本,對元素弱引用,可變類型;可以在訪問成員時copy
(注:NSHashTable與NSSet的區(qū)別:NSHashTable可以通過option設(shè)置元素弱引用/copyin,只有可變類型。但是添加對象的時候NSHashTable耗費時間是NSSet的兩倍。NSMapTable與NSDictionary的區(qū)別,同上)
3、屬性關(guān)鍵字assign、retain、weak、copy
assign:用于基本數(shù)據(jù)類型和結(jié)構(gòu)體。如果修飾對象的話,當銷毀時,屬性值不會自動設(shè)置為nil,可能造成野指針。
weak:對象引用計數(shù)為0時,屬性值也會自動置nil。
retain:強引用類型,ARC下相當于strong,但block不能用retain修飾,因為等同于assign不安全。
copy:會創(chuàng)建一個已經(jīng)存在對象的copy。
4、weak屬性如何自動置nil的?
runtime會對weak屬性進行內(nèi)存布局,構(gòu)建hash表:以weak屬性對象內(nèi)存地址為key,weak屬性值(weak自身地址)為value。當對象引用計數(shù)為0 dealloc時,會將weak屬性值自動置nil。
5、block的循環(huán)引用、內(nèi)部修改外部變量、三種block
block強引用self,self強引用blcok
內(nèi)部修改外部變量:block不允許修改外部變量的值,這里的外部變量指的是棧中指針的內(nèi)存地址。__block的作用是只要觀察到變量被block使用,就將外部變量在棧中的內(nèi)存地址放到堆中。
三種blcok:NSGlobalBlock(全局)、NSStackBlock(棧block)、NSMallocBlock(堆block)
6、KVO底層實現(xiàn)原理?手動觸發(fā)KVO?Swift如何實現(xiàn)KVO?
KVO原理:當觀察一個對象時,runtime會動態(tài)創(chuàng)建繼承自該對象的類,并重寫被觀察對象的setter方法,重寫的setter方法會負責在調(diào)用原setter方法前后通知所有觀察對象值的更改,最后會把該對象的isa指針指向創(chuàng)建的子類,對象就變成子類的實例。
如何手動觸發(fā)KVO:在setter方法里,手動實現(xiàn)NSObject兩個方法:willChangeValueForKey、didChangeValueForKey
Swift的KVO:繼承自NSObject的類,或者直接willSet/didSet實現(xiàn)。
7、category為什么不能添加屬性?怎么實現(xiàn)添加?與Extension的區(qū)別?category覆蓋原類方法?多個category調(diào)用順序?
runtime初始化時category的內(nèi)存布局已經(jīng)確定,沒有ivar,所以默認不能添加屬性。
使用runtime的關(guān)聯(lián)對象,并重寫setter和getter方法。
category是用來擴展類的功能的,而extension僅僅擴展定義,沒有源代碼的話是不能使用擴展的。
category方法會在runtime初始化的時候copy到原來前面,調(diào)用分類方法的時候直接返回,不再調(diào)用原類。category 其實并不是完全替換掉原來類的同名方法,只是 category 在方法列表的前面而已,所以我們只要順著方法列表找到最后一個對應(yīng)名字的方法,就可以調(diào)用原來類的方法。如何保持原類方法也調(diào)用(http://www.itdecent.cn/p/40e28c9f9da5)。
多個category的調(diào)用順序按照:Build Phases -> Complie Source 中的編譯順序。
8、load方法和initialize方法的異同?!饕f一下執(zhí)行時間,各自用途,沒實現(xiàn)子類的方法會不會調(diào)用父類的?
| load | Initialize | |
|---|---|---|
| 調(diào)用時機 | app啟動后,runtime初始化的時候 | 第一個方法調(diào)用前調(diào)用 |
| 調(diào)用順序 | 父類 -> 本類 -> 分類 | 父類 -> 本類(如果有分類直接調(diào)用分類,本類不會調(diào)用) |
| 沒實現(xiàn)子類的方法會不會調(diào)用父類 | 否 | 是 |
| 是否沿用父類實現(xiàn) | 否 | 是 |
9、對runtime的理解。——主要是方法調(diào)用時如何查找緩存,如何查找方法,找不到方法時怎么轉(zhuǎn)發(fā),對象的內(nèi)存布局
OC中向?qū)ο蟀l(fā)送消息時,runtime會根據(jù)對象的isa指針找到對象所屬的類,然后在該類的方法列表和父類的方法列表中尋找方法執(zhí)行。如果在最頂層父類中沒有找到方法執(zhí)行,就會進行消息轉(zhuǎn)發(fā):Method resoution(實現(xiàn)方法)、fast forwarding(轉(zhuǎn)發(fā)給其他對象)、normal forwarding(完整消息轉(zhuǎn)發(fā)??梢赞D(zhuǎn)發(fā)給多個對象)。
10、runtime中,SEL和IMP的區(qū)別?
每個類對象都有一個方法列表,方法列表存儲方法名、方法實現(xiàn)、參數(shù)類型,SEL是方法名(編號),IMP指向方法實現(xiàn)的首地址。
11、autoreleasepool的原理和使用場景
若干個autoreleasepoolpage組成的雙向鏈表的棧結(jié)構(gòu),objc_autoreleasepoolpush、objc_autoreleasepoolpop、objc_autorelease
使用場景:多次創(chuàng)建臨時變量導致內(nèi)存上漲時,需要延遲釋放
autoreleasepoolpage的內(nèi)存結(jié)構(gòu):4k存儲大小

12、Autorelase對象什么時候釋放?
在沒有手加Autorelease Pool的情況下,Autorelease對象是在當前runloop迭代結(jié)束時釋放的,而它能夠釋放的原因是系統(tǒng)在每個runloop迭代中都加入了自動釋放池Push和Pop。
13、runloop與線程的關(guān)系?runloop的mode?runloop的作用?內(nèi)部機制?
每一個線程都有一個runloop,主線程的runloop默認啟動。
mode:主要用來指定事件在運行時循環(huán)的優(yōu)先級。
作用:保持程序的持續(xù)運行、隨時處理各種事件、節(jié)省CPU資源(沒事件休息釋放資源)、渲染屏幕UI
14、iOS中使用的鎖、死鎖的發(fā)生與避免
@synchronized、信號量、NSLock等
死鎖:多個線程同時訪問同一資源,造成循環(huán)等待。GCD使用異步線程、并行隊列。
15、NSOperation和GCD的區(qū)別
GCD底層使用C語言編寫高效、NSOperation是對GCD的面向?qū)ο蟮姆庋b。對于特殊需求,如取消任務(wù)、設(shè)置任務(wù)優(yōu)先級、任務(wù)狀態(tài)監(jiān)聽,NSOperation使用起來更加方便。
NSOperation可以設(shè)置依賴關(guān)系,而GCD只能通過dispatch_barrier_async實現(xiàn)。
NSOperation可以通過KVO觀察當前operation執(zhí)行狀態(tài)(執(zhí)行、取消)
NSOperation可以設(shè)置自身優(yōu)先級(queuePriority)。GCD只能設(shè)置隊列優(yōu)先級(DISPATCH_QUEUQ_PRIORITY_DEFAULT),無法在執(zhí)行的block中設(shè)置優(yōu)先級。
NSOperation可以自定義operation,如NSInvationOperation/NSBlockOperation,而GCD執(zhí)行任務(wù)可以自定義封裝但沒有那么高的代碼復(fù)用度。
GCD高效,NSOperation開銷相對高。
16、OC與JS交互
攔截url
JavaScriptCore(只適用于UIWebView)
WKScriptMessageHandler(只適用于WKWebView)
WebViewJavaScriptBridge(第三方框架)
17、Swift相比OC有什么優(yōu)勢?
安全,Swift從語法上避免了很多未定義的行為,比如空值訪問、值類型等,可以提升項目穩(wěn)定性、降低崩潰率。
性能,Swift的語言設(shè)計讓方法調(diào)度通過靜態(tài)調(diào)度完成而不是OC的動態(tài)派發(fā),運行時效率優(yōu)于OC。
編碼效率,富有表現(xiàn)力的語法特性讓代碼更清晰易于理解,減少的代碼量約有30%-50%不等,讓開發(fā)人員更高效的支撐業(yè)務(wù)發(fā)展,提升了研發(fā)效率。
18、Struct、Class的區(qū)別
class可以繼承,struct不可以。
class是引用類型,struct是值類型。
struct在function里修改property時需要metating關(guān)鍵字修飾。
19、訪問控制關(guān)鍵字(public、open、private、filePrivate、internal)
public與open:public在module內(nèi)部中,class和func都可以被訪問/重載/繼承,外部只能訪問;而open都可以。
private與filePrivate:private修飾class/func,表示只能在當前class源文件/func內(nèi)部使用,外部不可以被繼承和訪問;而filePrivate表示只能在當前swift文件內(nèi)訪問。
internal:在整個模塊或者app內(nèi)都可以訪問,默認訪問級別,可寫可不寫。
20、OC與Swift混編
OC調(diào)用Swift:import "工程名-swift.h" @objc。
Swift調(diào)用OC:橋接文件。
21、map、filter、reduce?map與filter的區(qū)別?
map:數(shù)組中每個元素都經(jīng)過某個方法轉(zhuǎn)換,最后返回新的數(shù)組(xx.map({
0})。
flatmap:同map類似,區(qū)別在flatmap返回的數(shù)組不存在nil,并且會把optional解包;而且還可以把嵌套的數(shù)組變成一個([[1, 2], [3, 4], [5, 6]] -> [1, 2, 3, 4, 5, 6])。
filter:用戶篩選元素(xx.filter({$0 > 25},篩選出大于25的元素組成新數(shù)組)。
reduce:把數(shù)組元素組合計算為一個值,并接收初始值()。

22、guard與defer
gurad用于提前處理錯誤數(shù)據(jù),else退出程序,提高代碼可讀性。
defer延遲執(zhí)行,回收資源。多個defer反序執(zhí)行,后執(zhí)行內(nèi)層。
23、try、try?與try!
try:手動捕捉異常。
try?:系統(tǒng)幫我們處理,出現(xiàn)異常返回nil;沒有異常返回對應(yīng)的對象。
try!:直接告訴系統(tǒng),該方法沒有異常。如果出現(xiàn)異常程序會crash。
24、autoclosure:把一個表達式自動封裝成閉包
25、throws與rethrows:throws另一個throws時,將前者改為rethrows
26、App啟動優(yōu)化策略?main函數(shù)執(zhí)行前后怎么優(yōu)化?
啟動時間=pre-main耗時+main耗時。
-
pre-main階段優(yōu)化:
刪除無用代碼
抽象重復(fù)代碼
+load方法做的事情延遲到initialize中,或者+load的事情不宜花費太多時間。
減少不必要的framework,或者優(yōu)化已有framework。
-
main階段優(yōu)化:
didFinishLauchingWithOptions里代碼延后執(zhí)行。
首次啟動渲染的頁面優(yōu)化。
27、crash防護?
unrecognized selector crash
KVO crash
NSNotification crash
NSTimer crash
Container crash(數(shù)組越界、插nil等)
NSString carsh(字符串操作的crash)
Bad Access crash(野指針)
UI not on Main Thread crash(非主線程刷UI(機制待改善))。
28、內(nèi)存泄露問題?
主要集中在循環(huán)引用問題中,如block、NSTime、perform selector引用計數(shù)問題。
29、UI卡頓優(yōu)化?
- 用輕量對象代替重量對象,比如使用CALayer代替UIView。
- 減少不必要的屬性修改,比如UIView的frame。
- 將對象的銷毀放到后臺隊列中銷毀。
- 在后臺提前計算好布局,在需要時一次性調(diào)整好對應(yīng)的屬性。
- 對于復(fù)雜視圖,不是用自動布局。
- 當一個頁面上有大量文本時,文本在計算時使用NSAttributedString的方法來計算文本寬高和繪制文本。
- 自定義文本控件,使用CoreText對文本進行異步繪制,雖然麻煩,但可以避免多次計算,占用的內(nèi)存也比較小。
- 圖片的解碼,常見網(wǎng)絡(luò)圖片庫都自帶功能。
- 減少視圖的圓角、邊框、陰影和遮罩,避免離屏渲染帶來的CPU資源消耗,可以使用圖片代碼。
- 多個視圖重疊在一起時,GPU會把他們混合到一起,這個過程會消耗很多GPU資源,應(yīng)盡量減少視圖的層次。
30、架構(gòu)&設(shè)計模式?
- MVC設(shè)計模式介紹
- Model處理數(shù)據(jù),封裝了應(yīng)用程序的數(shù)據(jù),并定義操控和處理該數(shù)據(jù)的邏輯和運算。
- View管理的是可視層,管理信息的可視化顯示。
- Controller是溝通Model和View之間的橋梁,當用戶操作了View后,View通過Controller去更新對應(yīng)的數(shù)據(jù),而當數(shù)據(jù)改變后,Model通過Controller去調(diào)整View。
- 缺點是ViewController做了太多的事情,會很臃腫,解決的辦法是將一部分功能提取出來,放到一個單獨的類中處理,例如UITableViewDataSource。
- MVVM介紹、MVC與MVVM的區(qū)別?
- MVVM:Model-ViewController/View-ViewModel,雖然ViewController與View在技術(shù)上是不同的組件,但幾乎每次都是一起使用,所以進行了合并。Model依然是數(shù)據(jù)層。我們將ViewController中所有表示邏輯放到ViewModel中。
- MVVM可以更好的進行單元測試,可以針對ViewModel編寫單元測試。
- ReactiveCocoa的熱信號與冷信號。
- 緩存架構(gòu)設(shè)計LRU方案。
- LRU為最近最少使用,通過鏈表實現(xiàn),當插入一個數(shù)據(jù)時,將數(shù)據(jù)插入到列表的頭部,當訪問一個數(shù)據(jù)時,則將數(shù)據(jù)移動到鏈表的頭部,當鏈表滿了時,刪除鏈表尾部數(shù)據(jù)。
- SDWebImage源碼,如何實現(xiàn)解碼。
- AFNetworking源碼分析。
- 有四個文件夾,分別放著處理網(wǎng)絡(luò)請求的類、檢測網(wǎng)絡(luò)變化的類、處理網(wǎng)絡(luò)安全策略的類和處理網(wǎng)絡(luò)請求頭和響應(yīng)頭的類。
- 最核心的類是AFURLSessionManager,其中子類AFHTTPSessionManager是專門用來處理網(wǎng)絡(luò)請求的。
- AFSessionManager中的核心實現(xiàn)類是蘋果提供的NSURLSession和NSURLSessionDataTask。
- 組件化的實施,中間件的設(shè)計。
- 哈希表的實現(xiàn)原理?如何解決沖突?
- 哈希表的本質(zhì)是一個數(shù)組,數(shù)組中每一個元素稱為一個箱子(bin),箱子中存放的是鍵值對。數(shù)組長度即箱子數(shù)。
- 哈希表還有一個重要的屬性: 負載因子(load factor),它用來衡量哈希表的 空/滿 程度,一定程度上也可以體現(xiàn)查詢的效率。
- 負載因子越大,意味著哈希表越滿,越容易導致沖突,性能也就越低。因此,一般來說,當負載因子大于某個常數(shù)(可能是 1,或者 0.75 等)時,哈希表將自動擴容。
- 哈希表在自動擴容時,一般會創(chuàng)建兩倍于原來個數(shù)的箱子,因此即使 key 的哈希值不變,對箱子個數(shù)取余的結(jié)果也會發(fā)生改變,因此所有鍵值對的存放位置都有可能發(fā)生改變,這個過程也稱為重哈希(rehash)。
- 哈希表的擴容并不總是能夠有效解決負載因子過大的問題。
31、數(shù)據(jù)結(jié)構(gòu)&算法
- 快速排序、并歸排序。
- 快速排序:令第一個元素為基準元素,并設(shè)置兩個變量i和j, i在序列的最左端,j在序列的最右端。j 從右往左試探,直到 j 找到小于基準元素值的元素就停止先; i 從左往右試探,直到 i 找到大于基準元素值的元素就停止。當 i 和 j 都停止了后,交換 i 和 j 所指向的元素。交換后, j 、 i 按以上步驟繼續(xù)試探。直到 i 和 j 相遇之后,則i的值與基準元素交換,第一輪排序結(jié)束。第一輪排序結(jié)束后,分別對基準元素左右兩邊的序列重復(fù)以上步驟。
- 并歸排序:
- 二維數(shù)組查找(每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數(shù),輸入這樣的一個二維數(shù)組和一個整數(shù),判斷數(shù)組中是否含有該整數(shù))。
- 二叉樹的遍歷:判斷二叉樹的層數(shù)。
- 單鏈表判斷環(huán)。
32、計算機基礎(chǔ)
- http與https?socket編程?tcp、udp?get與post?
- tcp三次握手與四次握手。
- 進程與線程的區(qū)別。
- 速度。線程產(chǎn)生的速度快,通訊快,切換快,因為他們處于同一地址空間。
- 線程的資源利用率好。
- 線程使用公共變量或者內(nèi)存的時候需要同步機制,但進程不用。
轉(zhuǎn)自:https://zhuanlan.zhihu.com/p/77789398
自己敲一遍來加深記憶。