推薦閱讀:關(guān)于iOS面試題匯總(欄目持續(xù)更新)
各位最近應(yīng)該忙于跳槽與面試吧,畢竟金三銀四洼怔,珍惜好機(jī)會(huì),預(yù)祝大家面試順利通過镣隶,迎接大廠offer极谊。有需要資料可以私聊我了解
從輸入url到頁面展示到底發(fā)生了什么
- 1、輸入地址
- 2安岂、瀏覽器查找域名的 IP 地址
- 3轻猖、瀏覽器向 web 服務(wù)器發(fā)送一個(gè) HTTP 請(qǐng)求
- 4、服務(wù)器的永久重定向響應(yīng)
- 5嗜闻、瀏覽器跟蹤重定向地址
- 6蜕依、服務(wù)器處理請(qǐng)求
- 7、服務(wù)器返回一個(gè) HTTP 響應(yīng)
- 8、瀏覽器顯示 HTML
- 9样眠、瀏覽器發(fā)送請(qǐng)求獲取嵌入在 HTML 中的資源(如圖片友瘤、音頻、視頻檐束、CSS辫秧、JS等等)
iOS高頻(基礎(chǔ)+底層)面試題
你在開發(fā)過程中常用到哪些定時(shí)器,定時(shí)器時(shí)間會(huì)有誤差嗎被丧,如果有盟戏,為什么會(huì)有誤差?
iOS中常NSTimer甥桂、CADisplayLink柿究、GCD定時(shí)器,其中NSTimer黄选、CADisplayLink基于NSRunLoop實(shí)現(xiàn)蝇摸,故存在誤差,GCD定時(shí)器只依賴系統(tǒng)內(nèi)核办陷,相對(duì)一前兩者是比較準(zhǔn)時(shí)的貌夕。
誤差原因是:與NSRunLoop機(jī)制有關(guān), 因?yàn)镽unLoop每跑完一次圈再去檢查當(dāng)前累計(jì)時(shí)間是否已經(jīng)達(dá)到定時(shí)設(shè)置的間隔時(shí)間民镜,如果未達(dá)到啡专,RunLoop將進(jìn)入下一輪任務(wù),待任務(wù)結(jié)束之后再去檢查當(dāng)前累計(jì)時(shí)間制圈,而此時(shí)的累計(jì)時(shí)間可能已經(jīng)超過了定時(shí)器的間隔時(shí)間们童,故會(huì)存在誤差。
block是類嗎鲸鹦,有哪些類型?
block也算是個(gè)類,因?yàn)樗衖sa指針,block.isa的類型包括
- _NSConcreteGlobalBlock 跟全局變量一樣,設(shè)置在程序的數(shù)據(jù)區(qū)域(.data)中
- _NSConcreteStackBlock棧上(前面講的都是棧上的 block)
- _NSConcreteMallocBlock 堆上
這個(gè)isa可以按位運(yùn)算
block的分類病附,__block的作用,block循環(huán)引用產(chǎn)生的原因及解決辦法
- blcok分為全局blcok,堆block亥鬓,棧block。
- 在 MRC下:只要沒有訪問外部變量域庇,就是全局block嵌戈。訪問了外部變量,就是棧block听皿。顯示地調(diào)用[block copy]就是堆block熟呛。
- 在 ARC下:只要沒有訪問外部變量,就是全局block尉姨。如果訪問了外部變量庵朝,那么在訪問外部變量之前存儲(chǔ)在棧區(qū),訪問外部變量之后存儲(chǔ)在堆區(qū)。
- __block的作用:將外部變量的傳遞形式由值傳遞變?yōu)橹羔槀鬟f九府,從而可以獲取并且修改外部變量的值椎瘟。同樣,外部變量的修改侄旬,也會(huì)影響block函數(shù)的輸出肺蔚。
- block循環(huán)引用問題:當(dāng)一個(gè)類的對(duì)象持有block,block里面又引用了這個(gè)對(duì)象儡羔,那么就是一個(gè)循環(huán)引用的關(guān)系宣羊。可以用strong-weak-dance的方法解除循環(huán)引用汰蜘。
淺復(fù)制和深復(fù)制的區(qū)別仇冯?
答案:淺層復(fù)制:只復(fù)制指向?qū)ο蟮闹羔槪粡?fù)制引用對(duì)象本身族操。
深層復(fù)制:復(fù)制引用對(duì)象本身苛坚。
意思就是說我有個(gè)A對(duì)象,復(fù)制一份后得到A_copy對(duì)象后坪创,對(duì)于淺復(fù)制來說炕婶,A和A_copy指向的是同一個(gè)內(nèi)存資源,復(fù)制的只不過是是一個(gè)指針莱预,對(duì)象本身資源
還是只有一份柠掂,那如果我們對(duì)A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對(duì)象同樣被修改,這其實(shí)違背了我們復(fù)制拷貝的一個(gè)思想依沮。深復(fù)制就好理解了,內(nèi)存中存在了
兩份獨(dú)立對(duì)象本身涯贞。
用網(wǎng)上一哥們通俗的話將就是:
淺復(fù)制好比你和你的影子,你完蛋危喉,你的影子也完蛋
深復(fù)制好比你和你的克隆人宋渔,你完蛋,你的克隆人還活著辜限。
類別的作用皇拣?繼承和類別在實(shí)現(xiàn)中有何區(qū)別?
答案:category 可以在不獲悉薄嫡,不改變?cè)瓉泶a的情況下往里面添加新的方法氧急,只能添加,不能刪除修改毫深。
并且如果類別和原來類中的方法產(chǎn)生名稱沖突吩坝,則類別將覆蓋原來的方法,因?yàn)轭悇e具有更高的優(yōu)先級(jí)哑蔫。
類別主要有3個(gè)作用:
(1)將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中钉寝。
(2)創(chuàng)建對(duì)私有方法的前向引用弧呐。
(3)向?qū)ο筇砑臃钦絽f(xié)議。
繼承可以增加嵌纲,修改或者刪除方法俘枫,并且可以增加屬性。
oc中的協(xié)議和java中的接口概念有何不同疹瘦?
答案:OC中的代理有2層含義崩哩,官方定義為 formal和informal protocol。前者和Java接口一樣言沐。
informal protocol中的方法屬于設(shè)計(jì)模式考慮范疇邓嘹,不是必須實(shí)現(xiàn)的,但是如果有實(shí)現(xiàn)险胰,就會(huì)改變類的屬性汹押。
其實(shí)關(guān)于正式協(xié)議,類別和非正式協(xié)議我很早前學(xué)習(xí)的時(shí)候大致看過起便,也寫在了學(xué)習(xí)教程里
“非正式協(xié)議概念其實(shí)就是類別的另一種表達(dá)方式“這里有一些你可能希望實(shí)現(xiàn)的方法棚贾,你可以使用他們更好的完成工作”。
這個(gè)意思是榆综,這些是可選的妙痹。比如我門要一個(gè)更好的方法,我們就會(huì)申明一個(gè)這樣的類別去實(shí)現(xiàn)鼻疮。然后你在后期可以直接使用這些更好的方法怯伊。
這么看,總覺得類別這玩意兒有點(diǎn)像協(xié)議的可選協(xié)議判沟。"
現(xiàn)在來看耿芹,其實(shí)protocal已經(jīng)開始對(duì)兩者都統(tǒng)一和規(guī)范起來操作,因?yàn)橘Y料中說“非正式協(xié)議使用interface修飾“挪哄,
現(xiàn)在我們看到協(xié)議中兩個(gè)修飾詞:“必須實(shí)現(xiàn)(@requied)”和“可選實(shí)現(xiàn)(@optional)”吧秕。
oc中可修改和不可以修改類型。
答案:可修改不可修改的集合類迹炼。這個(gè)我個(gè)人簡(jiǎn)單理解就是可動(dòng)態(tài)添加修改和不可動(dòng)態(tài)添加修改一樣砸彬。
比如NSArray和NSMutableArray。前者在初始化后的內(nèi)存控件就是固定不可變的斯入,后者可以添加等拿霉,可以動(dòng)態(tài)申請(qǐng)新的內(nèi)存空間。
關(guān)于多態(tài)性
答案:多態(tài)咱扣,子類指針可以賦值給父類。
這個(gè)題目其實(shí)可以出到一切面向?qū)ο笳Z言中涵防,
因此關(guān)于多態(tài)闹伪,繼承和封裝基本最好都有個(gè)自我意識(shí)的理解沪铭,也并非一定要把書上資料上寫的能背出來。
最重要的是轉(zhuǎn)化成自我理解偏瓤。
通知和協(xié)議的不同之處杀怠?
答案:協(xié)議有控制鏈(has-a)的關(guān)系,通知沒有厅克。
首先我一開始也不太明白赔退,什么叫控制鏈(專業(yè)術(shù)語了~)。但是簡(jiǎn)單分析下通知和代理的行為模式证舟,我們大致可以有自己的理解
簡(jiǎn)單來說硕旗,通知的話,它可以一對(duì)多女责,一條消息可以發(fā)送給多個(gè)消息接受者漆枚。
代理按我們的理解,到不是直接說不能一對(duì)多抵知,比如我們知道的明星經(jīng)濟(jì)代理人墙基,很多時(shí)候一個(gè)經(jīng)濟(jì)人負(fù)責(zé)好幾個(gè)明星的事務(wù)。
只是對(duì)于不同明星間刷喜,代理的事物對(duì)象都是不一樣的残制,一一對(duì)應(yīng),不可能說明天要處理A明星要一個(gè)發(fā)布會(huì)掖疮,代理人發(fā)出處理發(fā)布會(huì)的消息后初茶,別稱B的
發(fā)布會(huì)了。但是通知就不一樣氮墨,他只關(guān)心發(fā)出通知纺蛆,而不關(guān)心多少接收到感興趣要處理。
因此控制鏈(has-a從英語單詞大致可以看出规揪,單一擁有和可控制的對(duì)應(yīng)關(guān)系桥氏。
線程和進(jìn)程的區(qū)別?
1> 一個(gè)應(yīng)用程序?qū)?yīng)一個(gè)進(jìn)程猛铅,一個(gè)進(jìn)程幫助程序占據(jù)一塊存儲(chǔ)空間
2> 要想在進(jìn)程中執(zhí)行任務(wù)字支,就必須開啟線程,一條線程就代表一個(gè)任務(wù)
3> 一個(gè)進(jìn)程中允許開啟多條線程奸忽,也就是同時(shí)執(zhí)行多個(gè)任務(wù)
Objective-C如何對(duì)內(nèi)存管理的,說說你的看法和解決方法?
1> 每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器堕伪,每個(gè)新對(duì)象的計(jì)數(shù)器是1,當(dāng)對(duì)象的計(jì)數(shù)器減為0時(shí)栗菜,就會(huì)被銷毀
2> 通過retain可以讓對(duì)象的計(jì)數(shù)器+1欠雌、release可以讓對(duì)象的計(jì)數(shù)器-1
3> 還可以通過autorelease pool管理內(nèi)存
如果用ARC,編譯器會(huì)自動(dòng)生成管理內(nèi)存的代碼
堆和棧的區(qū)別疙筹?
1> 堆空間的內(nèi)存是動(dòng)態(tài)分配的富俄,一般存放對(duì)象禁炒,并且需要手動(dòng)釋放內(nèi)存
2> 棧空間的內(nèi)存由系統(tǒng)自動(dòng)分配霍比,一般存放局部變量等幕袱,不需要手動(dòng)管理內(nèi)存
- 為什么很多內(nèi)置的類,如TableView的delegate的屬性是assign不是retain悠瞬?
1> tableView的代理一般都是它所屬的控制器们豌,控制器會(huì)對(duì)它內(nèi)部的view做一次retain操作
2> 假設(shè)tableView也對(duì)代理(控制器)做一次retain操作,那么就出現(xiàn)循環(huán)retain問題
- 定義屬性時(shí)浅妆,什么情況使用copy望迎、assign、retain狂打?
1> copy:NSString擂煞、Block等類型
2> assign:基本數(shù)據(jù)類型
3> retain:OC對(duì)象類型
App冷啟動(dòng)優(yōu)化?
App冷啟動(dòng)優(yōu)化方案博客非常之多趴乡,概括總結(jié)大致如下:
pre-main優(yōu)化:減少動(dòng)態(tài)靜態(tài)庫(kù)对省,合并動(dòng)態(tài)庫(kù),移除廢棄第三方庫(kù)及所依賴的系統(tǒng)庫(kù)晾捏,二進(jìn)制重排(抖音優(yōu)化方案)
runtime對(duì)類的注冊(cè)蒿涎,類對(duì)象的初始化,load方法加載階段:精簡(jiǎn)類惦辛,合并分類劳秋,移除廢棄分類等等
main函數(shù)之后,推遲對(duì)三方庫(kù)注冊(cè)及延時(shí)調(diào)用耗時(shí)操作函數(shù)胖齐〔J纾可以通過Instruments-->Time Profiler: 性能分析,定位耗時(shí)函數(shù)
pushViewController和presentViewController有什么區(qū)別
兩者都是在多個(gè)試圖控制器間跳轉(zhuǎn)的函數(shù)
presentViewController提供的是一個(gè)模態(tài)視圖控制器(modal)
pushViewController提供一個(gè)棧控制器數(shù)組呀伙,push/pop
多線程的底層實(shí)現(xiàn)?
1.首先搞清楚什么是線程补履、什么是多線程
2.Mach是第一個(gè)以多線程方式處理任務(wù)的系統(tǒng),因此多線程的底層實(shí)現(xiàn)機(jī)制是基于Mach的線程
3.開發(fā)中很少用Mach級(jí)的線程剿另,因?yàn)镸ach級(jí)的線程沒有提供多線程的基本特征箫锤,線程之間是獨(dú)立的
4.開發(fā)中實(shí)現(xiàn)多線程的方案
C語言的POSIX接口:#include <pthread.h>
OC的NSThread
C語言的GCD接口(性能最好,代碼更精簡(jiǎn))
OC的NSOperation和NSOperationQueue (基于GCD)
哪些情況下使用kvo會(huì)崩潰雨女,怎么防護(hù)崩潰谚攒?
使用不當(dāng) 會(huì)crash,比如:
- 添加和移出不是成對(duì)出現(xiàn)且存在多線程添加KVO的情況,經(jīng)常遇到的crash是移出 - 內(nèi)存dealloc的時(shí)候 或者對(duì)象銷毀前沒有正確移出Observer
如何防護(hù)?
1.注意移出對(duì)象 匹配
2.內(nèi)存野指針問題,一定要在對(duì)象銷毀前移出觀察者 3.可以使用第三方庫(kù)BlockKit添加KVO,blockkit內(nèi)部會(huì)自動(dòng)移除Observer避免crash.
簡(jiǎn)述iOS中的內(nèi)存管理方式
iOS的內(nèi)存管理用的是引用計(jì)數(shù)的方法氛堕,分為MRC(手動(dòng)引用計(jì)數(shù))和ARC(自動(dòng)引用計(jì)數(shù))馏臭。
MRC:開發(fā)者手動(dòng)地進(jìn)行retain和release操作,對(duì)每個(gè)對(duì)象的retainCount進(jìn)行+1,-1操作讼稚,當(dāng)retainCount為0時(shí)位喂,系統(tǒng)會(huì)自動(dòng)釋放對(duì)象內(nèi)存浪耘。
ARC:開發(fā)者通過聲明對(duì)象的屬性為strong,weak,retain,assign來管理對(duì)象的引用計(jì)數(shù),被strong和retain修飾的屬性變量系統(tǒng)會(huì)自動(dòng)對(duì)所修飾變量的引用計(jì)數(shù)進(jìn)行自增自減操作塑崖,同樣地,retainCount為0時(shí)痛倚,系統(tǒng)會(huì)釋放對(duì)象內(nèi)存规婆。
通知,代理蝉稳,block抒蚜,KVO的使用場(chǎng)景分別是什么,有什么區(qū)別耘戚?
通知: 適用于毫無關(guān)聯(lián)的頁面之間或者系統(tǒng)消息的傳遞嗡髓,屬于一對(duì)多的信息傳遞關(guān)系。例如系統(tǒng)音量的改變收津,系統(tǒng)狀態(tài)的改變饿这,應(yīng)用模式的設(shè)置和改變,都比較適合用通知去傳遞信息撞秋。
代理: 一對(duì)一的信息傳遞方式长捧,適用于相互關(guān)聯(lián)的頁面之間的信息傳遞,例如push和present出來的頁面和原頁面之間的信息傳遞吻贿。
block: 一對(duì)一的信息傳遞方式串结,效率會(huì)比代理要高(畢竟是直接取IMP指針的操作方式)。適用的場(chǎng)景和代理差不多舅列,都是相互關(guān)聯(lián)頁面之間的頁面?zhèn)髦怠?/p>
KVO: 屬性監(jiān)聽肌割,監(jiān)聽對(duì)象的某一屬性值的變化狀況,當(dāng)需要監(jiān)聽對(duì)象屬性改變的時(shí)候使用帐要。例如在UIScrollView中把敞,監(jiān)聽contentOffset,既可以用KVO宠叼,也可以用代理先巴。但是其他一些情況,比如說UIWebView的加載進(jìn)度,AVPlayer的播放進(jìn)度冒冬,就只能用KVO來監(jiān)聽了伸蚯,否則獲取不到對(duì)應(yīng)的屬性值。