這篇文章用來嘗試回答落影大佬的面試題空厌,原文:iOS面試小結(jié)
一、基礎(chǔ)知識
1银酬、Objective-C基礎(chǔ)
為了切合iOS面試的主題嘲更,面試官通常都會從這一塊知識開始入手。OC的知識非常龐雜揩瞪,有時(shí)候遇到熟悉的內(nèi)容就很了解赋朦,如果沒有接觸過可能就沒有印象。比如說:viewDidLoad 的觸發(fā)時(shí)機(jī)是發(fā)生在什么時(shí)候李破?以及延伸的問題宠哄,viewDidLoad 與loadView的關(guān)系以及先后順序。
所以這部分知識嗤攻,更合適問一些基礎(chǔ)毛嫉、共性的問題。比如說:
常見的property有哪些屬性妇菱?各自的屬性應(yīng)用場景有哪些承粤?
介紹KVO和KVC的區(qū)別?KVO是否會引起循環(huán)引用闯团?如果觀察對象已經(jīng)釋放密任,會導(dǎo)致什么現(xiàn)象?用NSNotification 替代KVO偷俭,觀察對象已釋放會如何浪讳?如何手動實(shí)現(xiàn)KVO?
如何創(chuàng)建一個(gè)字符串常量涌萤?在.h聲明并且實(shí)現(xiàn)會有什么問題淹遵?
category和extension的區(qū)別?category的實(shí)現(xiàn)原理负溪?extension是否可以和category寫在同一個(gè)文件透揣?
答:
- 控制器的生命周期:
- loadView
- viewDidLoad
- viewWillappear
- viewWillLayoutsubViews
- viewDidLayoutsubViews
- viewDidappear
- viewWillDisAppear
- viewDidDisAppear
- dealloc
- KVO和KVC:
- KVO是鍵值觀察,是對屬性添加觀察川抡,當(dāng)屬性值發(fā)生變化時(shí)會通知訂閱者辐真。屬于觀察者模式在iOS中的實(shí)現(xiàn)。
- 注意崖堤,KVO的觸發(fā)條件是調(diào)用set方法侍咱,如果通過_成員變量則不觸發(fā)。
- KVC是鍵值對編碼密幔,說人話就是通過屬性字符串名稱改變和獲取屬性
- KVO不會引起循環(huán)引用楔脯,oberver沒有對self強(qiáng)引用
- 觀察對象已釋放,會產(chǎn)生崩潰胯甩,NSNotification則不會
- 手動調(diào)用KVO的方法是在set方法前后分別執(zhí)行
willChangeValueForKey
和didChangeValueForKey
- 變量昧廷、常量堪嫂、宏
//宏
#define HSCoder @"漢斯哈哈哈"
//變量
NSString *HSCoder = @"漢斯哈哈哈";
//常量,四種寫法
static const NSString *HSCoder = @"漢斯哈哈哈";
const NSString *HSCoder = @"漢斯哈哈哈";
NSString const *HSCoder = @"漢斯哈哈哈";
NSString * const HSCoder = @"漢斯哈哈哈";
- 宏:只是在預(yù)處理器里進(jìn)行文本替換木柬,沒有類型皆串,不做任何類型檢查,編譯器可以對相同的字符串進(jìn)行優(yōu)化眉枕。只保存一份到 .rodata 段愚战。甚至有相同后綴的字符串也可以優(yōu)化,你可以用GCC 編譯測試齐遵,"Hello world" 與 "world" 兩個(gè)字符串寂玲,只存儲前面一個(gè)。取的時(shí)候只需要給前面和中間的地址梗摇,如果是整形拓哟、浮點(diǎn)型會有多份拷貝,但這些數(shù)寫在指令中伶授。占的只是代碼段而已断序,大量用宏會導(dǎo)致二進(jìn)制文件變大
- 變量:共享一塊內(nèi)存空間,就算項(xiàng)目中N處用到糜烹,也不會分配N塊內(nèi)存空間违诗,可以被修改,在編譯階段會執(zhí)行類型檢查
- 常量:共享一塊內(nèi)存空間疮蹦,就算項(xiàng)目中N處用到诸迟,也不會分配N塊內(nèi)存空間,可以根據(jù)const修飾的位置設(shè)定能否修改愕乎,在編譯階段會執(zhí)行類型檢查
2阵苇、內(nèi)存管理
ARC和MRC,iOS開發(fā)者需要對兩種內(nèi)存管理方式都熟悉感论。一個(gè)了解MRC的開發(fā)者绅项,遇到CF開頭的函數(shù)怎么辦?
很常見的面試切入點(diǎn)是從ARC的實(shí)現(xiàn)原理開始比肄,引入__strong/__weak/__unsafe_unretained/__autoreleasing多個(gè)關(guān)鍵詞的區(qū)別快耿,再聯(lián)想到循環(huán)引用,block實(shí)現(xiàn)原理芳绩,block持有外部的局部變量掀亥,autoReleasePool的使用,autoReleasePool與MRC的autorelease區(qū)別示括。
3铺浇、Runtime
Runtime機(jī)制介紹;
介紹isa垛膝、屬性列表鳍侣、方法列表、協(xié)議列表吼拥;
消息傳遞機(jī)制如何查找方法倚聚;
Category實(shí)現(xiàn)原理;
method swizzling原理凿可;
imp和selector惑折;
答:
- Runtime是OC語言在C語言基礎(chǔ)上實(shí)現(xiàn)面向?qū)ο蠛蛣討B(tài)性具體實(shí)現(xiàn)的一套C語言API。
- isa枯跑,對象指針地址惨驶,在arm64之后經(jīng)過優(yōu)化變成一個(gè)共用體(union),還使用位域存儲更多信息:
- 是否關(guān)聯(lián)過對象敛助、是否有C++析構(gòu)函數(shù)粗卜、是否完成初始化、是否被弱引用指向過纳击、對象是否正在釋放续扔、引用計(jì)數(shù)是否過大無法儲存,若無法儲存則存在sideTable類的屬性中焕数。
- 屬性列表纱昧、方法列表、協(xié)議列表堡赔,都存在類對象中识脆,實(shí)例對象通過isa指向類對象。
- 編譯期善已,屬性列表存璃、方法列表、協(xié)議列表存在class_ro_t中雕拼,通過runtime添加的話則存在class_rw_t中纵东。
- 消息傳遞機(jī)制如何查找方法?三步走流程
消息發(fā)送:消息發(fā)送方receiver通過isa找到自己的class啥寇,從cache查找方法緩存偎球,找不到則從class_rw_t查找,找不到繼續(xù)通過isa查找superClass進(jìn)行相同查找順序辑甜,找到后將方法緩存到cache衰絮,找不到進(jìn)入第二步
動態(tài)方法解析
消息轉(zhuǎn)發(fā)
4.Category實(shí)現(xiàn)原理
- Category主要實(shí)現(xiàn)對已有類擴(kuò)展方法,通過runtime甚至可以添加協(xié)議磷醋、屬性猫牡,但是不可以添加成員變量
- Category主要是由runtime運(yùn)行時(shí)動態(tài)把擴(kuò)展方法添加到類的方法列表。
- 什么時(shí)候被添加邓线?程序啟動時(shí)淌友,由dyld鏈接器初始化runtime環(huán)境煌恢,由runtime添加,由
read_images
方法插入到類方法列表前面
- method swizzling原理
- Method Swizzling 用于改變一個(gè)已經(jīng)存在的 selector 實(shí)現(xiàn)震庭。我們可以在程序運(yùn)行時(shí)瑰抵,通過改變 selector 所在 Class(類)的 method list(方法列表)的映射從而改變方法的調(diào)用。其實(shí)質(zhì)就是交換兩個(gè)方法的 IMP(方法實(shí)現(xiàn))器联。
- imp和selector二汛;
- IMP代表函數(shù)的具體實(shí)現(xiàn)
- SEL代表方法\函數(shù)名,一般叫做選擇器拨拓,底層結(jié)構(gòu)跟char *類似
- 可以通過@selector()和sel_registerName()獲得
- 可以通過sel_getName()和NSStringFromSelector()轉(zhuǎn)成字符串
- 不同類中相同名字的方法肴颊,所對應(yīng)的方法選擇器是相同的
4、RunLoop
runloop概述渣磷;
與線程的關(guān)系婿着;
與FPS的關(guān)系;
RunLoop的實(shí)際應(yīng)用幸海;
答:
- runloop概述祟身;
iOS程序運(yùn)行過程中循環(huán)做的一些事情,包括定時(shí)器物独、事件袜硫、GCD、觸摸事件挡篓,在空閑時(shí)休眠婉陷,在忙活時(shí)啟動,達(dá)到節(jié)省資源目的官研。 - 與線程的關(guān)系秽澳;
每條線程都有唯一的一個(gè)與之對應(yīng)的RunLoop對象
RunLoop保存在一個(gè)全局的Dictionary里,線程作為key戏羽,RunLoop作為value
線程剛創(chuàng)建時(shí)并沒有RunLoop對象担神,RunLoop會在第一次獲取它時(shí)創(chuàng)建
RunLoop會在線程結(jié)束時(shí)銷毀
主線程的RunLoop已經(jīng)自動獲取(創(chuàng)建)始花,子線程默認(rèn)沒有開啟RunLoop
- 與FPS的關(guān)系妄讯;
- RunLoop的實(shí)際應(yīng)用;
控制線程生命周期(線程笨嵯活)
解決NSTimer在滑動時(shí)停止工作的問題
監(jiān)控應(yīng)用卡頓
性能優(yōu)化
5亥贸、iOS系統(tǒng)
介紹scheme原理;
微信如何實(shí)現(xiàn)呼起第三方app浇垦?網(wǎng)頁又如何呼起APP炕置?
Push通知實(shí)現(xiàn)原理?客戶端A直接向客戶端B發(fā)Push是否可行?
代碼簽名朴摊;
沙盒機(jī)制默垄;
地址空間隨機(jī)化;
答
- 利用scheme:協(xié)議進(jìn)行url跳轉(zhuǎn)仍劈。
- .使用通用鏈接厕倍。通用鏈接就是HTTP協(xié)議的普通URL,通過在服務(wù)器上配置一些文件,配合應(yīng)用.實(shí)現(xiàn)客戶點(diǎn)擊網(wǎng)頁鏈接之后直接打開信E投等應(yīng)用.客戶在微信\QQ中點(diǎn)擊鏈接時(shí)不再需要點(diǎn)擊右上'在Safari瀏覽器打開'才能打開軟件,實(shí)現(xiàn)客戶操作的無縫跳轉(zhuǎn),讓客戶體驗(yàn)更加連貫,更順暢.
- 通知原理就是服務(wù)器給蘋果服務(wù)器發(fā)送推送通知請求寡壮,因?yàn)閕OS應(yīng)用和apple服務(wù)器時(shí)長連接贩疙,所以可以通過apple服務(wù)器給app直接推送消息。
- 代碼簽名:是對可執(zhí)行文件或代碼進(jìn)行數(shù)字簽名以確認(rèn)軟件作者及保證軟件在簽名后未被修改或損壞的措施况既。此措施使用加密散列來驗(yàn)證真實(shí)性和完整性这溅。
- 沙盒機(jī)制:每個(gè)app都是單獨(dú)存放在自己的沙盒中,不同應(yīng)用不能返回其他應(yīng)用棒仍,這樣可以保證應(yīng)用的安全性悲靴。
6、編譯原理
介紹整個(gè)編譯的流程莫其;
靜態(tài)庫癞尚、動態(tài)庫的區(qū)別;
靜態(tài)連接乱陡、動態(tài)鏈接的過程和區(qū)別浇揩;
在VC.h文件引入VC+Test.h(Category)會如何;
答
- 編譯過程
- 預(yù)處理:處理以#開頭的命令憨颠,刪除注釋胳徽,解開宏定義等
- 編譯:詞法分析、語法分析爽彤、語義分析养盗、中間代碼生成與優(yōu)化,最終生成匯編代碼
- 匯編:將匯編代碼翻譯成機(jī)器碼适篙,生成.o目標(biāo)文件
- 鏈接:將多個(gè).o目標(biāo)文件和其他函數(shù)庫鏈接成可執(zhí)行文件
- 動態(tài)庫和靜態(tài)庫的區(qū)別往核?
- 區(qū)別:靜態(tài)庫在程序鏈接成可執(zhí)行文件時(shí)就已經(jīng)鏈接完成,動態(tài)庫是在程序啟動嚷节、運(yùn)行時(shí)才進(jìn)行鏈接
- 動態(tài)鏈接和靜態(tài)鏈接的區(qū)別聂儒?
- 同上
6.在VC.h文件引入VC+Test.h(Category)會如何?會編譯報(bào)錯(cuò)丹喻,因?yàn)榛ハ喟?/p>
7薄货、多線程
7.1.多線程有哪些實(shí)現(xiàn)方式 ?
7.2.pthread碍论、NSThread谅猾、GCD、NSOperationQueue有哪些應(yīng)用場景?
7.3.>多線程如何進(jìn)行線程同步税娜?
7.4.信號量坐搔、鎖、代碼塊敬矩、原子變量常見有哪些應(yīng)用場景概行?
7.5.實(shí)現(xiàn)一個(gè)變量的讀寫鎖:讀共享,寫互斥弧岳;
7.6.如何用GCD實(shí)現(xiàn)100個(gè)任務(wù)執(zhí)行凳忙,但是最高并發(fā)為10個(gè)任務(wù)?
//建立任務(wù)組
dispatch_group_t group = dispatch_group_create();
//設(shè)置信號量大小
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
//創(chuàng)建全局隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//添加實(shí)現(xiàn)任務(wù)
for (int i = 0; i < 100; i++) {
//semphore值為0時(shí)會一直等待執(zhí)行禽炬。當(dāng)>=1時(shí)執(zhí)行下面的代碼涧卵。可通過一次腹尖,會將semphore的值減1.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//監(jiān)視queue隊(duì)列
dispatch_group_async(group, queue, ^{
NSLog(@"這里在執(zhí)行耗時(shí)操作----%i",i);
sleep(2);
//當(dāng)前線程執(zhí)行完成后柳恐,使semaphore的值加1,這樣热幔,如果semphore的值就加1乐设,會觸發(fā)dispatch_semaphore_wait執(zhí)行一條代碼
dispatch_semaphore_signal(semaphore);
});
}
//永遠(yuǎn)地監(jiān)聽Group中的任務(wù)是否執(zhí)行完成。
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
7.7. GCD和線程的關(guān)系绎巨?GCD并發(fā)隊(duì)列的線程爆炸近尚?
8、網(wǎng)絡(luò)原理
介紹TCP三次握手认烁?
socket編程中肿男,何時(shí)進(jìn)行三次握手?如何用socket發(fā)送數(shù)據(jù)却嗡?
HTTP協(xié)議中request和response有哪些數(shù)據(jù)組成部分舶沛?
在瀏覽器輸入U(xiǎn)RL到頁面加載發(fā)生了什么?
HTTP斷點(diǎn)續(xù)傳窗价;
HTTP中間人攻擊如庭;(重點(diǎn))
HTTPS實(shí)現(xiàn)原理;(加密通信原理)
HTTPS中間人攻擊撼港;
DNS劫持坪它;
9、Xcode
LLDB調(diào)試技巧:如何查看堆棧帝牡、修改內(nèi)存往毡、監(jiān)控內(nèi)存值變化、執(zhí)行語句靶溜;
Xcode中的scheme配置是什么开瞭?
General中的Project和Target用處懒震?
Certificate、Provisioning Profile嗤详、App ID的關(guān)系个扰;
Image Assets Catalogs是什么?