給iOS中高級求職者的一份面試題解答

前段時(shí)間更新了一篇 給iOS中高級面試官的一份招聘要求 收到很多小伙伴的點(diǎn)贊與關(guān)注跷车∶芮浚可能有很多小伙伴已經(jīng)帶著我在那篇文章給大家提供的一些面試技巧 & 其中的面試題 已經(jīng)開始招聘了只洒!這里應(yīng)大家要求,對里面的面試題提供相關(guān)答案距芬!相信無論是面試官還是求職者都是有所收獲的~~

PS:篇幅有點(diǎn)長涝开,大家可以關(guān)注或者點(diǎn)贊收藏以備不時(shí)之需!?蜃小舀武!

iOS基礎(chǔ)

1:講講你對atomic & nonatomic的理解

  • 1寻馏、原子操作對線程安全并無任何安全保證左腔。被 atomic 修飾的屬性(不重載設(shè)置器和訪問器)只保證了對數(shù)據(jù)讀寫的完整性摇锋,也就是原子性肮柜,但是與對象的線程安全無關(guān)。
  • 2、線程安全有保障瑞躺、對性能有要求的情況下可使用 nonatomic替代atomic拷邢,當(dāng)然也可以一直使用atomic
  • 3:詳細(xì)參考

2:被 weak 修飾的對象在被釋放的時(shí)候會發(fā)生什么牙咏?是如何實(shí)現(xiàn)的奢浑?知道sideTable 么阵面?里面的結(jié)構(gòu)可以畫出來么授帕?

被weak修飾的對象在被釋放時(shí)候會置為nil丽涩,不同于assign;

Runtime 維護(hù)了一個(gè) weak表含潘,用于存儲指向某個(gè)對象的所有weak指針模叙。weak表 其實(shí)是一個(gè) hash(哈希)表Key 是所指對象的地址鞋屈,Valueweak指針 的地址(這個(gè)地址的值是所指對象指針的地址)數(shù)組范咨。

  • 1、初始化時(shí):runtime 會調(diào)用 objc_initWeak函數(shù)厂庇,初始化一個(gè)新的 weak指針 指向?qū)ο蟮牡刂贰?/li>
  • 2渠啊、添加引用時(shí):objc_initWeak函數(shù) 會調(diào)用 objc_storeWeak() 函數(shù)objc_storeWeak() 的作用是更新指針指向权旷,創(chuàng)建對應(yīng)的弱引用表替蛉。
  • 3、釋放時(shí)拄氯,調(diào)用 clearDeallocating函數(shù)躲查。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有 weak指針地址的數(shù)組,然后遍歷這個(gè)數(shù)組把其中的數(shù)據(jù)設(shè)為 nil译柏,最后把這個(gè) entryweak表中刪除镣煮,最后清理對象的記錄。
  • 4:詳細(xì)參考
struct SideTable {
    // 保證原子操作的自旋鎖
    spinlock_t slock;
    // 引用計(jì)數(shù)的 hash 表
    RefcountMap refcnts;
    // weak 引用全局 hash 表
    weak_table_t weak_table;
}

struct weak_table_t {
    // 保存了所有指向指定對象的 weak 指針
    weak_entry_t *weak_entries;
    // 存儲空間
    size_t    num_entries;
    // 參與判斷引用計(jì)數(shù)輔助量
    uintptr_t mask;
    // hash key 最大偏移值
    uintptr_t max_hash_displacement;
};

3:block 用什么修飾鄙麦?strong 可以典唇?

  • block 本身是像對象一樣可以 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)?block 變量默認(rèn)是聲明為棧變量的,為了能夠在block的聲明域外使用影所,所以要把 block 拷貝(copy)到堆蹦肴,所以說為了 block 屬性聲明和實(shí)際的操作一致,最好聲明為 copy猴娩。
  • 詳細(xì)參考

4:block 為什么能夠捕獲外界變量阴幌? __block做了什么事勺阐?

研究Block的捕獲外部變量就要除去函數(shù)參數(shù)這一項(xiàng),下面一一根據(jù)這4種變量類型的捕獲情況進(jìn)行分析矛双。

  • 自動(dòng)變量
  • 靜態(tài)變量
  • 靜態(tài)全局變量
  • 全局變量

首先 全局變量global_i靜態(tài)全局變量static_global_j 的值增加渊抽,以及它們被Block 捕獲進(jìn)去,這一點(diǎn)很好理解议忽,因?yàn)槭侨值睦撩疲饔糜蚝軓V,所以Block捕獲了它們進(jìn)去之后栈幸,在Block里面進(jìn)行++操作愤估,Block結(jié)束之后,它們的值依舊可以得以保存下來速址。

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_a_0 *a; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

__main_block_impl_0結(jié)構(gòu)體 就是這樣把自動(dòng)變量捕獲進(jìn)來的玩焰。也就是說,在執(zhí)行 Block 語法的時(shí)候芍锚,Block 語法表達(dá)式所使用的自動(dòng)變量的值是被保存進(jìn)了Block的結(jié)構(gòu)體實(shí)例中昔园,也就是 Block 自身中。

這里值得說明的一點(diǎn)是并炮,如果Block外面還有很多自動(dòng)變量默刚,靜態(tài)變量,等等逃魄,這些變量在Block里面并不會被使用到羡棵。那么這些變量并不會被Block捕獲進(jìn)來,也就是說并不會在構(gòu)造函數(shù)里面?zhèn)魅胨鼈兊闹怠?/p>

Block捕獲外部變量僅僅只捕獲Block閉包里面會用到的值嗅钻,其他用不到的值,它并不會去捕獲店展。

5:談?wù)勀銓κ录膫鬟f鏈和響應(yīng)鏈的理解

  • 一:響應(yīng)者鏈
    UIResponser包括了各種Touch message 的處理养篓,比如開始,移動(dòng)赂蕴,停止等等柳弄。常見的 UIResponserUIView及子類UIViController,APPDelegate概说,UIApplication等等碧注。

回到響應(yīng)鏈,響應(yīng)鏈?zhǔn)怯?code>UIResponser組成的糖赔,那么是按照哪種規(guī)則形成的萍丐。

  • A: 程序啟動(dòng)
    UIApplication會生成一個(gè)單例,并會關(guān)聯(lián)一個(gè)APPDelegate放典。APPDelegate作為整個(gè)響應(yīng)鏈的根建立起來逝变,而``UIApplication會將自己與這個(gè)單例鏈接基茵,即UIApplicationnextResponser(下一個(gè)事件處理者)為APPDelegate`。

  • B:創(chuàng)建UIWindow
    程序啟動(dòng)后壳影,任何的UIWindow被創(chuàng)建時(shí)拱层,UIWindow內(nèi)部都會把nextResponser設(shè)置為UIApplication單例UIWindow初始化rootViewController,rootViewControllernextResponser會設(shè)置為UIWindow

  • C:UIViewController初始化
    loadView, VCviewnextResponser會被設(shè)置為VC.

  • D:addSubView
    addSubView操作過程中宴咧,如果子subView不是VC的View,那么subViewnextResponser會被設(shè)置為superView根灯。如果是VCView,那就是 subView -> subView.VC ->superView如果在中途,subView.VC被釋放掺栅,就會變成subView.nextResponser = superView

image

我們使用一個(gè)現(xiàn)實(shí)場景來解釋這個(gè)問題:當(dāng)一個(gè)用點(diǎn)擊屏幕上的一個(gè)按鈕烙肺,這個(gè)過程具體發(fā)生了什么。

    1. 用戶觸摸屏幕柿冲,系統(tǒng)硬件進(jìn)程會獲取到這個(gè)點(diǎn)擊事件茬高,將事件簡單處理封裝后存到系統(tǒng)中,由于硬件檢測進(jìn)程和當(dāng)前App進(jìn)程是兩個(gè)進(jìn)程假抄,所以進(jìn)程兩者之間傳遞事件用的是端口通信怎栽。硬件檢測進(jìn)程會將事件放到APP檢測的那個(gè)端口。
  • 2.APP啟動(dòng)主線程RunLoop會注冊一個(gè)端口事件宿饱,來檢測觸摸事件的發(fā)生熏瞄。當(dāng)事件到達(dá),系統(tǒng)會喚起當(dāng)前APP主線程的RunLoop谬以。來源就是App主線程事件强饮,主線程會分析這個(gè)事件。

  • 3.最后为黎,系統(tǒng)判斷該次觸摸是否導(dǎo)致了一個(gè)新的事件, 也就是說是否是第一個(gè)手指開始觸碰邮丰,如果是,系統(tǒng)會先從響應(yīng)網(wǎng)中 尋找響應(yīng)鏈铭乾。如果不是剪廉,說明該事件是當(dāng)前正在進(jìn)行中的事件產(chǎn)生的一個(gè)Touch message, 也就是說已經(jīng)有保存好的響應(yīng)鏈

  • 二:事件傳遞鏈

通過兩種方法來做這個(gè)事情炕檩。

// 先判斷點(diǎn)是否在View內(nèi)部斗蒋,然后遍歷subViews
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;  
//判斷點(diǎn)是否在這個(gè)View內(nèi)部
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   // default returns YES if point is in bounds
  • A: 流程

  • 1:先判斷該層級是否能夠響應(yīng)(1.alpha>0.01 2.userInteractionEnabled == YES 3.hidden = NO)

  • 2:判斷改點(diǎn)是否在view內(nèi)部,

  • 3:如果在那么遍歷子view繼續(xù)返回可響應(yīng)的view,直到?jīng)]有笛质。

  • B:常見問題

  • 父view設(shè)置為不可點(diǎn)擊泉沾,子view可以點(diǎn)擊嗎

  • 不可以,hit test 到父view就截止了

  • 子view設(shè)置view不可點(diǎn)擊不影響父類點(diǎn)擊

  • 同父view覆蓋不影響點(diǎn)擊

  • 手勢對responder方法的影響

  • C:實(shí)際用法

  • 點(diǎn)一一個(gè)圓形控件妇押,如何實(shí)現(xiàn)只點(diǎn)擊圓形區(qū)域有效跷究,重載pointInside。此時(shí)可將外部的點(diǎn)也判斷為內(nèi)部的點(diǎn)舆吮,反之也可以揭朝。

  • 事件響應(yīng)鏈在復(fù)雜功能界面進(jìn)行不同控件間的通信队贱,簡便某些場景下優(yōu)于代理和block

6:談?wù)?KVC 以及 KVO 的理解?

7:RunLoop 的作用是什么潭袱?它的內(nèi)部工作機(jī)制了解么柱嫌?

字面意思是“消息循環(huán)、運(yùn)行循環(huán)”屯换,runloop內(nèi)部實(shí)際上就是一個(gè)do-while循環(huán)编丘,它在循環(huán)監(jiān)聽著各種事件源、消息彤悔,對他們進(jìn)行管理并分發(fā)給線程來執(zhí)行嘉抓。

  • 1.通知觀察者將要進(jìn)入運(yùn)行循環(huán)。
    線程和 RunLoop 之間是一一對應(yīng)的

  • 2.通知觀察者將要處理計(jì)時(shí)器晕窑。

  • 3.通知觀察者任何非基于端口的輸入源即將觸發(fā)抑片。

  • 4.觸發(fā)任何準(zhǔn)備觸發(fā)的基于非端口的輸入源。

  • 5.如果基于端口的輸入源準(zhǔn)備就緒并等待觸發(fā)杨赤,請立即處理該事件敞斋。轉(zhuǎn)到第9步。

  • 6.通知觀察者線程即將睡眠疾牲。

  • 7.將線程置于睡眠狀態(tài)植捎,直到發(fā)生以下事件之一:

    • 事件到達(dá)基于端口的輸入源。
    • 計(jì)時(shí)器運(yùn)行阳柔。
    • 為運(yùn)行循環(huán)設(shè)置的超時(shí)值到期焰枢。
    • 運(yùn)行循環(huán)被明確喚醒。
  • 8.通知觀察者線程被喚醒舌剂。

  • 9.處理待處理事件济锄。

    • 如果觸發(fā)了用戶定義的計(jì)時(shí)器,則處理計(jì)時(shí)器事件并重新啟動(dòng)循環(huán)霍转。轉(zhuǎn)到第2步拟淮。
    • 如果輸入源被觸發(fā),則傳遞事件谴忧。
    • 如果運(yùn)行循環(huán)被明確喚醒但尚未超時(shí),請重新啟動(dòng)循環(huán)角虫。轉(zhuǎn)到第2步沾谓。
  • 10.通知觀察者運(yùn)行循環(huán)已退出。

8:蘋果是如何實(shí)現(xiàn) autoreleasepool的戳鹅?

arc下編譯器會優(yōu)化成

void *context = objc_autoreleasePoolPush();
// {}中的代碼
objc_autoreleasePoolPop(context);
  • 向一個(gè)結(jié)構(gòu)AutoreleasePoolPage均驶,中寫入需要自動(dòng)釋放的對象,類似一種標(biāo)記枫虏,調(diào)用objc_autoreleasePoolPop(context)后妇穴,就會把這中間的對象release一下爬虱。
  • 這里要注意的是,方法返回值是怎么做到自動(dòng)釋放的腾它?
  • 其使用Thread Local Storage(TLS)線程局部存儲跑筝,每次存入線程或者從線程取出來。
  • 我們沒有卸載{}中的自動(dòng)釋放對象瞒滴,會在每個(gè)runloop結(jié)束時(shí)候去釋放曲梗,相當(dāng)于一個(gè)大的autoreleasepool中。
  • 參考文章
  • 蘋果是如何實(shí)現(xiàn)autoreleasepool的

9:談?wù)勀銓?FRP (函數(shù)響應(yīng)式) 的理解妓忍,延伸一下 RxSwift 或者 RAC虏两!

參考文章:RxSwift(1)— 初探
看這一篇文章也就夠了!然后結(jié)合 RxSwift 映射到 RAC世剖!函數(shù)響應(yīng)式的思想是不變的定罢!至于內(nèi)部的封裝有所不同,但是最終卻是殊途同歸旁瘫!

10:平時(shí)開發(fā)有沒有玩過 Instrument 祖凫?

分析:這里的內(nèi)容非常有意思,對于一個(gè)iOS高級開發(fā)人員境蜕,我覺得還有很有必要掌握的蝙场!尤其開發(fā)3-5年,如果沒有掌握這些內(nèi)容我覺得是不合格的

我個(gè)人建議在掌握面試題的同時(shí)還需要求職者更多的去分析和拓展粱年!比如你的探索思路售滤,你在這個(gè)知識點(diǎn)意外的延伸。還有你再實(shí)際開發(fā)過程的落地台诗!而這些都是加分項(xiàng)完箩!

Runtime

1:什么是 isa,isa 的作用是什么拉队?

2:一個(gè)實(shí)例對象的isa 指向什么弊知?類對象指向什么?元類isa 指向什么粱快?

  • 參考文章
  • 實(shí)例對象的isa 指向類
  • 類對象的isa指向元類
  • 元類isa 指向根元類
  • 3:objc 中類方法和實(shí)例方法有什么本質(zhì)區(qū)別和聯(lián)系秩彤?

  • 參考文章

類方法:

  • 1.類方法是屬于類對象的
  • 2.類方法只能通過類對象調(diào)用
  • 3.類方法中的self是類對象
  • 4.類方法可以調(diào)用其他的類方法
  • 5.類方法中不能訪問成員變量
  • 6.類方法中不能直接調(diào)用對象方法

實(shí)例方法:

  • 1.實(shí)例方法是屬于實(shí)例對象的
  • 2.實(shí)例方法只能通過實(shí)例對象調(diào)用
  • 3.實(shí)例方法中的self是實(shí)例對象
  • 4.實(shí)例方法中可以訪問成員變量
  • 5.實(shí)例方法中直接調(diào)用實(shí)例方法
  • 6.實(shí)例方法中也可以調(diào)用類方法(通過類名)

4:loadinitialize 的區(qū)別?

+load

  • 1事哭、只要程序啟動(dòng)就會將所有類的代碼加載到內(nèi)存中(在main函數(shù)執(zhí)行之前), 放到代碼區(qū)(無論該類有沒有被使用到都會被調(diào)用)
  • 2漫雷、+load方法會在當(dāng)前類被加載到內(nèi)存的時(shí)候調(diào)用, 有且僅會調(diào)用一次
  • 3、當(dāng)父類和子類都實(shí)現(xiàn)+load方法時(shí), 會先調(diào)用父類的+load方法, 再調(diào)用子類的+load方法
  • 4鳍咱、先加載原始類降盹,再加載分類的+load方法
  • 5、子類實(shí)現(xiàn)或不實(shí)現(xiàn) load ,父類都會調(diào)用load
  • 6谤辜、多個(gè)類都實(shí)現(xiàn)+load方法蓄坏,+load方法的調(diào)用順序价捧,與Compile Sources中出現(xiàn)的順序一致

load方法在Apple官方文檔中的描述

+initialize

  • 1、當(dāng)類第一次被使用的時(shí)候就會調(diào)用(創(chuàng)建類對象的時(shí)候)
  • 2涡戳、initialize方法在整個(gè)程序的運(yùn)行過程中只會被調(diào)用一次, 無論你使用多少次這個(gè)類都只會調(diào)用一次
  • 3结蟋、initialize用于對某一個(gè)類進(jìn)行一次性的初始化
  • 4、先調(diào)用父類的initialize再調(diào)用子類的initialize
  • 5妹蔽、當(dāng)子類未實(shí)現(xiàn)initialize方法時(shí)椎眯,會把父類的實(shí)現(xiàn)繼承過來調(diào)用一遍,再次之前父類的initialize方法會被優(yōu)先調(diào)用一次
  • 6胳岂、當(dāng)有多個(gè)Category都實(shí)現(xiàn)了initialize方法编整,會覆蓋類中的方法,只執(zhí)行一個(gè)(會執(zhí)行Compile Sources 列表中最后一個(gè)Categoryinitialize方法)

initialize方法在Apple官方文檔中的描述

5:_objc_msgForward 函數(shù)是做什么的乳丰?直接調(diào)用會發(fā)生什么問題掌测?

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

  • 1.調(diào)用resolveInstanceMethod:方法,允許用戶在此時(shí)為該Class動(dòng)態(tài)添加實(shí)現(xiàn)什燕。如果有實(shí)現(xiàn)了粘勒,則調(diào)用并返回。如果仍沒實(shí)現(xiàn)屎即,繼續(xù)下面的動(dòng)作庙睡。
  • 2.調(diào)用forwardingTargetForSelector:方法,嘗試找到一個(gè)能響應(yīng)該消息的對象技俐。如果獲取到乘陪,則直接轉(zhuǎn)發(fā)給它。如果返回了nil雕擂,繼續(xù)下面的動(dòng)作啡邑。
  • 3.調(diào)用methodSignatureForSelector:方法,嘗試獲得一個(gè)方法簽名井赌。如果獲取不到谤逼,則直接調(diào)用doesNotRecognizeSelector拋出異常。
  • 4.調(diào)用forwardInvocation:方法仇穗,將地3步獲取到的方法簽名包裝成Invocation傳入森缠,如何處理就在這里面了。

如果直接調(diào)用這個(gè)方法仪缸,就算實(shí)現(xiàn)了想調(diào)用的方法,也不會被調(diào)用列肢,會直接走消息轉(zhuǎn)發(fā)步驟恰画。

6:簡述下 Objective-C 中調(diào)用方法的過程

  • Objective-C是動(dòng)態(tài)語言宾茂,每個(gè)方法在運(yùn)行時(shí)會被動(dòng)態(tài)轉(zhuǎn)為消息發(fā)送,即:objc_msgSend(receiver, selector)拴还,整個(gè)過程介紹如下:
  • objc在向一個(gè)對象發(fā)送消息時(shí)跨晴,runtime庫會根據(jù)對象的isa指針找到該對象實(shí)際所屬的類
  • 然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行
  • 如果,在最頂層的父類(一般也就NSObject)中依然找不到相應(yīng)的方法時(shí)片林,程序在運(yùn)行時(shí)會掛掉并拋出異常 unrecognized selector sent to XXX
  • 但是在這之前端盆,objc的運(yùn)行時(shí)會給出三次拯救程序崩潰的機(jī)會,這三次拯救程序奔潰的說明見問題《什么時(shí)候會報(bào)unrecognized selector的異撤逊猓》中的說明

PS:Runtime 鑄就了Objective-C 是動(dòng)態(tài)語言的特性焕妙,使得C語言具備了面向?qū)ο蟮奶匦裕诔绦蜻\(yùn)行期創(chuàng)建弓摘,檢查焚鹊,修改類、對象及其對應(yīng)的方法涕刚,這些操作都可以使用runtime中的對應(yīng)方法實(shí)現(xiàn)置谦。

7:能否想向編譯后得到的類中增加實(shí)例變量军洼?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量?為什么璧针?

  • 1.不能向編譯后得到的類增加實(shí)例變量
  • 2.能向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量

解釋:

  • 1.編譯后的類已經(jīng)注冊在runtime中,類結(jié)構(gòu)體中的objc_ivar_list實(shí)例變量的鏈表和instance_size實(shí)例變量的內(nèi)存大小已經(jīng)確定, runtime會調(diào)用 class_setvarlayoutclass_setWeaklvarLayout來處理 strong weak引用.所以不能向存在的類中添加實(shí)例變量
  • 2.運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量,調(diào)用class_addIvar函數(shù).但是的在調(diào)用objc_allocateClassPair之后, objc_registerClassPair之前,原因同上.

8:談?wù)勀銓η忻婢幊痰睦斫?/p>

維基百科對于切面編程(AOP)的解釋是這樣的:面向切面的程序設(shè)計(jì)(aspect-oriented programming,AOP渊啰,又譯作面向側(cè)面的程序設(shè)計(jì)探橱、觀點(diǎn)導(dǎo)向編程、剖面導(dǎo)向程序設(shè)計(jì))是計(jì)算機(jī)科學(xué)中的一個(gè)術(shù)語虽抄,指一種程序設(shè)計(jì)范型走搁。該范型以一種稱為切面的語言構(gòu)造為基礎(chǔ),切面是一種新的模塊化機(jī)制迈窟,用來描述分散在對象私植、類、函數(shù))中的橫切關(guān)注點(diǎn)车酣。參考文章

分析:Runtime 這個(gè)模塊iOS面試無論初中高都會面試曲稼。我覺得這個(gè)模塊不光只是僅僅問問關(guān)于知識點(diǎn)內(nèi)容,我更新想要聽到求職者在這里面的爬坑探索辛歷路程湖员!Runtime這個(gè)模塊是刷開頁面開發(fā)的關(guān)鍵點(diǎn)贫悄!

網(wǎng)絡(luò)&多線程

1:HTTP的缺陷是什么?

HTTP 主要有這些不足娘摔,例舉如下窄坦。

  • 通信使用明文(不加密),內(nèi)容可能會被竊聽
  • 不驗(yàn)證通信方的身份,因此有可能遭遇偽裝
  • 無法證明報(bào)文的完整性鸭津,所以有可能已遭篡改

這些問題不僅在HTTP上出現(xiàn)彤侍,其他未加密的協(xié)議中也會存在這類問題。

2:談?wù)勅挝帐帜媲鳎拇螕]手盏阶!為什么是三次握手,四次揮手闻书?

參考文章 我覺得這個(gè)地方還是需要自我理解名斟,用自己的話去表達(dá)出來!

3:socket 連接和 Http 連接的區(qū)別

http 是基于 socket 之上的魄眉。socket 是一套完整的 tcp,udp協(xié)議的接口砰盐。

  • HTTP協(xié)議:簡單對象訪問協(xié)議,對應(yīng)于應(yīng)用層杆融,HTTP協(xié)議是基于TCP連接的楞卡。
    • tcp協(xié)議:對應(yīng)于傳輸層。
    • ip協(xié)議:對應(yīng)于網(wǎng)絡(luò)層脾歇。

TCP/IP是傳輸層協(xié)議蒋腮,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸,而HTTP協(xié)議是應(yīng)用層協(xié)議藕各,主要解決如何包裝數(shù)據(jù)池摧。

Socket是對TCP/IP 協(xié)議的封裝,它本身不是協(xié)議激况,而是一個(gè)調(diào)用接口作彤,通過Socket,我們才能使用TCP/IP協(xié)議乌逐。

  • http連接:就是所謂的短連接竭讳,即客戶端向服務(wù)器端發(fā)送一次請求,服務(wù)器端響應(yīng)后連接即會斷掉浙踢。
  • socket連接:就是所謂的長連接绢慢,理論上客戶端和服務(wù)器端一旦建立起連接將不會主動(dòng)斷掉,但是由于各種環(huán)境因素可能會使連接斷開洛波。

http是客戶端用http協(xié)議進(jìn)行請求胰舆,發(fā)送請求時(shí)候需要封裝http請求頭,并綁定請求的數(shù)據(jù)蹬挤,服務(wù)器一般有web服務(wù)器配合缚窿。http請求方式為客戶端主動(dòng)發(fā)起請求,服務(wù)器才能給響應(yīng)焰扳,一次請求完畢后則斷開連接以節(jié)省資源倦零。服務(wù)器不能主動(dòng)給客戶端響應(yīng)误续。iPhone主要使用的類是NSUrlConnectionsocket是客戶端跟服務(wù)器直接使用socket“套接字”進(jìn)行拼接扫茅,并沒有規(guī)定連接后斷開女嘲,所以客戶端和服務(wù)器可以保持連接,雙方都可以主動(dòng)發(fā)送數(shù)據(jù)诞帐。一般在游戲開發(fā)或者股票開發(fā)這種即時(shí)性很強(qiáng)的并且保持發(fā)送數(shù)據(jù)量比較大的場合使用。主要類是CFSocketRef爆雹。

  • UDP:是用戶數(shù)據(jù)報(bào)協(xié)議:主要用在實(shí)時(shí)性要求高以及對質(zhì)量相對較弱的地方停蕉,但面對現(xiàn)在高質(zhì)量的線路容易丟包。
  • TCP:是傳輸控制協(xié)議钙态,是面向連接的慧起,,運(yùn)行環(huán)境必然要求其可靠性不可丟失包有良好的擁塞控制機(jī)制册倒。

4:什么時(shí)候POP網(wǎng)絡(luò)蚓挤,有了 Alamofire 封裝網(wǎng)絡(luò) URLSession為什么還要用Moya

POP網(wǎng)絡(luò):面向協(xié)議編程的網(wǎng)絡(luò)能夠大大降低耦合度驻子!網(wǎng)絡(luò)層下沉灿意,業(yè)務(wù)層上浮。中間利用 POP網(wǎng)絡(luò)Moya 隔開崇呵。如果你的項(xiàng)目是 RxSwift 函數(shù)響應(yīng)式的也沒有關(guān)系缤剧!因?yàn)橛?RxMoya

參考文章:

5:如何實(shí)現(xiàn) dispatch_once

+ (instancetype)sharedInstance
{
    /*定義相應(yīng)類實(shí)例的靜態(tài)變量;
    意義:函數(shù)內(nèi)定義靜態(tài)變量域慷,無論該函數(shù)被調(diào)用多少次荒辕,
         在內(nèi)存中只初始化一次,并且能保存最后一次賦的值
    */
    static ClassName *instance = nil;
    /*定義一個(gè)dispatch_once_t(其實(shí)也就是整型)靜態(tài)變量犹褒,
    意義:作為標(biāo)識下面dispatch_once的block是否已執(zhí)行過抵窒。
         static修飾會默認(rèn)將其初始化為0,當(dāng)值為0時(shí)才會執(zhí)行block叠骑。
         當(dāng)block執(zhí)行完成李皇,底層會將onceToken設(shè)置為1,這也就是為什
         么要傳onceToken的地址(static修飾的變量可以通過地址修改
         onceToken的值)座云,同時(shí)底層會加鎖來保證這個(gè)方法是線程安全的
    */
    static dispatch_once_t onceToken;
    /*只要當(dāng)onceToken == 0時(shí)才會執(zhí)行block疙赠,否則直接返回靜態(tài)變量instance*/
    dispatch_once(&onceToken, ^{
        instance = [[ClassName alloc] init];
        //...
    });
    return instance;
}

iOS原理之CGD-dispatch_once的底層實(shí)現(xiàn)

6:能否寫一個(gè)讀寫鎖?談?wù)劸唧w的分析
7:什么時(shí)候會出現(xiàn)死鎖朦拖?如何避免圃阳?
8:有哪幾種鎖?各自的原理璧帝?它們之間的區(qū)別是什么捍岳?最好可以結(jié)合使用場景來說

分析:這個(gè)模塊可能是一般開發(fā)人員的盲區(qū)。對于這一塊一定要有自己的理解!學(xué)習(xí)的方向就是查漏補(bǔ)缺锣夹,一步一個(gè)吃掉页徐!如果你一整塊去啃,你會發(fā)現(xiàn)很枯燥银萍!雖然開發(fā)過程中你可能用不到变勇,但是面試這一塊是你必須要掌握的!

數(shù)據(jù)結(jié)構(gòu)

1.數(shù)據(jù)結(jié)構(gòu)的存儲一般常用的有幾種贴唇?各有什么特點(diǎn)搀绣?

數(shù)據(jù)的存儲結(jié)構(gòu)是數(shù)據(jù)結(jié)構(gòu)的一個(gè)重要內(nèi)容。在計(jì)算機(jī)中戳气,數(shù)據(jù)的存儲結(jié)構(gòu)可以采取如下四中方法來表現(xiàn)链患。

  • 順序存儲方式

簡單的說,順序存儲方式就是在一塊連續(xù)的存儲區(qū)域
一個(gè)接著一個(gè)的存放數(shù)據(jù)瓶您。順序存儲方式把邏輯上相連的結(jié)點(diǎn)存儲在物理位置上相鄰的存儲單元里麻捻,結(jié)點(diǎn)間的邏輯關(guān)系由存儲單元的鄰接掛安息來體現(xiàn)。順序存儲方式也稱為順序存儲結(jié)構(gòu)(sequentialstorage structure)呀袱,一般采用數(shù)組或者結(jié)構(gòu)數(shù)組來描述贸毕。
線性存儲方式主要用于線性邏輯結(jié)構(gòu)的數(shù)據(jù)存放,而對于圖和樹等非線性邏輯結(jié)構(gòu)則不適用压鉴。

  • 鏈接存儲方式

鏈接存儲方式比較靈活崖咨,其不要求邏輯上相鄰的結(jié)點(diǎn)在物理位置上相鄰,結(jié)點(diǎn)間的邏輯關(guān)系由附加的引用字段表示油吭。一個(gè)結(jié)點(diǎn)的引用字段往往指導(dǎo)下一個(gè)結(jié)點(diǎn)的存放位置击蹲。
鏈接存儲方式也稱為鏈接式存儲結(jié)構(gòu)(LinkedStorage Structure),一般在原數(shù)據(jù)項(xiàng)中增加應(yīng)用類型來表示結(jié)點(diǎn)之間的位置關(guān)系婉宰。

  • 索引存儲方式

索引存儲方式是采用附加索引表的方式來存儲結(jié)點(diǎn)信息的一種存儲方式歌豺。索引表由若干個(gè)索引項(xiàng)組成。索引存儲方式中索引項(xiàng)的一般形式為:(關(guān)鍵字心包、地址)类咧。其中,關(guān)鍵字是能夠唯一標(biāo)識一個(gè)結(jié)點(diǎn)的數(shù)據(jù)項(xiàng)蟹腾。

  • 索引存儲方式還可以細(xì)分為如下兩類:

    • 稠密索引(Dense Index):這種方式中每個(gè)結(jié)點(diǎn)在索引表中都有一個(gè)索引項(xiàng)痕惋。其中,索引項(xiàng)的地址指示結(jié)點(diǎn)所在的的存儲位置娃殖;

    • 稀疏索引(Spare Index):這種方式中一組結(jié)點(diǎn)在索引表中只對應(yīng)一個(gè)索引項(xiàng)值戳。其中,索引項(xiàng)的地址指示一組結(jié)點(diǎn)的起始存儲位置炉爆。

  • 散列存儲方式

散列存儲方式是根據(jù)結(jié)點(diǎn)的關(guān)鍵字直接計(jì)算出該結(jié)點(diǎn)的存儲地址的一種存儲的方式堕虹。
在實(shí)際應(yīng)用中卧晓,往往需要根據(jù)具體數(shù)據(jù)結(jié)構(gòu)來決定采用哪一種存儲方式。同一邏輯結(jié)構(gòu)采用不同額存儲方法赴捞,可以得到不同的存儲結(jié)構(gòu)逼裆。而且這四種節(jié)本存儲方法,既可以單獨(dú)使用赦政,也可以組合起來對數(shù)據(jù)結(jié)構(gòu)進(jìn)行存儲描述胜宇。

2.集合結(jié)構(gòu) 線性結(jié)構(gòu) 樹形結(jié)構(gòu) 圖形結(jié)構(gòu)
3.單向鏈表 雙向鏈表 循環(huán)鏈表
4.數(shù)組和鏈表區(qū)別
5.堆、棧和隊(duì)列

6.輸入一棵二叉樹的根結(jié)點(diǎn)掸屡,求該樹的深度?

如果一棵樹只有一個(gè)結(jié)點(diǎn)然评,它的深度為1。 如果根結(jié)點(diǎn)只有左子樹而沒有右子樹狈究, 那么樹的深度應(yīng)該是其左子樹的深度加1碗淌,同樣如果根結(jié)點(diǎn)只有右子樹而沒有左子樹,那么樹的深度應(yīng)該是其右子樹的深度加1. 如果既有右子樹又有左子樹抖锥, 那該樹的深度就是其左亿眠、右子樹深度的較大值再加1。

public static int treeDepth(BinaryTreeNode root) {
    if (root == null) {
        return 0;
    }
    int left = treeDepth(root.left);
    int right = treeDepth(root.right);
    return left > right ? (left + 1) : (right + 1);
}

7.輸入一課二叉樹的根結(jié)點(diǎn)磅废,判斷該樹是不是平衡二叉樹纳像?

  • (1)需要重復(fù)遍歷節(jié)點(diǎn)多次的解法
  • (2)每個(gè)節(jié)點(diǎn)只需遍歷一次的解法
  • 參考文章:

算法

1.時(shí)間復(fù)雜度

計(jì)算機(jī)科學(xué)中,時(shí)間復(fù)雜性拯勉,又稱時(shí)間復(fù)雜度竟趾,算法時(shí)間復(fù)雜度是一個(gè)函數(shù),它定性描述該算法的運(yùn)行時(shí)間宫峦。這是一個(gè)代表算法輸入值的字符串的長度的函數(shù)岔帽。時(shí)間復(fù)雜度常用大O符號表述,不包括這個(gè)函數(shù)的低階項(xiàng)和首項(xiàng)系數(shù)导绷。使用這種方式時(shí)犀勒,時(shí)間復(fù)雜度可被稱為是漸近的,亦即考察輸入值大小趨近無窮時(shí)的情況妥曲。
時(shí)間復(fù)雜性

2.空間復(fù)雜度
空間復(fù)雜度(Space Complexity)是對一個(gè)算法在運(yùn)行過程中臨時(shí)占用存儲空間大小的量度贾费,記做S(n)=O(f(n))。比如直接插入排序時(shí)間復(fù)雜度是O(n^2),空間復(fù)雜度是O(1) 檐盟。而一般的遞歸算法就要有O(n)的空間復(fù)雜度了褂萧,因?yàn)槊看芜f歸都要存儲返回信息。一個(gè)算法的優(yōu)劣主要從算法的執(zhí)行時(shí)間和所需要占用的存儲空間兩個(gè)方面衡量遵堵。
時(shí)間復(fù)雜度&空間復(fù)雜度

3.常用的排序算法

  • 1箱玷、冒泡排序
  • 2怨规、選擇排序
  • 3、插入排序
  • 4锡足、希爾排序
  • 5波丰、快速排序
  • 6、歸并排序
  • 7舶得、堆排序
  • 常見的7種排序算法

4.字符串反轉(zhuǎn)

- (NSString *)reversalString:(NSString *)originString{
    NSString *resultStr = @"";
    for (NSInteger i = originString.length -1; i >= 0; i--) {
      NSString *indexStr = [originString substringWithRange:NSMakeRange(i, 1)];
      resultStr = [resultStr stringByAppendingString:indexStr];
    }
  return resultStr;
}

5.鏈表反轉(zhuǎn)(頭差法)

public Node reverseList(){
        Node cur = head;
        Node prev = null;
        Node curNext = head.next;
        Node reverHead = null;
        while(cur!=null){
            cur.next = prev;
            cur = curNext;
            prev = cur;
            curNext = curNext.next;
        }
        reverHead = cur;
        return reverHead;
}

> 6.有序數(shù)組合并

```objc
- (void)merge {
    /*
     有序數(shù)組A:1掰烟、4、5沐批、8纫骑、10...1000000,有序數(shù)組B:2九孩、3先馆、6、7躺彬、9...999998煤墙,A、B兩個(gè)數(shù)組不相互重復(fù)宪拥,請合并成一個(gè)有序數(shù)組C仿野,寫出代碼和時(shí)間復(fù)雜度。
     */
    //(1).
    NSMutableArray *A = [NSMutableArray arrayWithObjects:@4,@5,@8,@10,@15, nil];
//    NSMutableArray *B = [NSMutableArray arrayWithObjects:@2,@6,@7,@9,@11,@17,@18, nil];
    NSMutableArray *B = [NSMutableArray arrayWithObjects:@2,@6,@7,@9,@11,@12,@13, nil];
    NSMutableArray *C = [NSMutableArray array];
    int count = (int)A.count+(int)B.count;
    int index = 0;
    for (int i = 0; i < count; i++) {
        if (A[0]<B[0]) {
            [C addObject:A[0]];
            [A removeObject:A[0]];
        }
        else if (B[0]<A[0]) {
            [C addObject:B[0]];
            [B removeObject:B[0]];
        }
        if (A.count==0) {
            [C addObjectsFromArray:B];
            NSLog(@"C = %@",C);
            index = i+1;
            NSLog(@"index = %d",index);
            return;
        }
        else if (B.count==0) {
            [C addObjectsFromArray:A];
            NSLog(@"C = %@",C);
            index = i+1;
            NSLog(@"index = %d",index);
            return;
        }
    }
    //(2).
    //時(shí)間復(fù)雜度
    //T(n) = O(f(n)):用"T(n)"表示她君,"O"為數(shù)學(xué)符號脚作,f(n)為同數(shù)量級,一般是算法中頻度最大的語句頻度缔刹。
    //時(shí)間復(fù)雜度:T(n) = O(index);
}

7.查找第一個(gè)只出現(xiàn)一次的字符(Hash查找)

兩個(gè)思路:

  • 1:hash?不同編譯器對字符數(shù)據(jù)的處理不一樣球涛,所以hash之前先把字符類型轉(zhuǎn)成無符號類型;
  • 2校镐,空間換時(shí)間宾符,用buffer數(shù)組記錄當(dāng)前只找到一次的字符,避免二次遍歷灭翔。
# define SIZE 256
char GetChar(char str[])
{
  if(!str)
    return 0;
  char* p = NULL;
  unsigned count[SIZE] = {0};
  char buffer[SIZE];
  char* q = buffer;
  for(p=str; *p!=0; p++)
  {
    if(++count[(unsigned char)*p] == 1)
      *q++ = *p;
  }
  
  for (p=buffer; p<q; p++)
  {
    if(count[(unsigned char)*p] == 1)
    return *p;
  }
return 0;
}

8.查找兩個(gè)子視圖的共同父視圖

這個(gè)問的其實(shí)是數(shù)據(jù)結(jié)構(gòu)中的二叉樹魏烫,查找一個(gè)普通二叉樹中兩個(gè)節(jié)點(diǎn)最近的公共祖先問題
假設(shè)兩個(gè)視圖為UIViewAUIViewC肝箱,其中 UIViewA繼承于UIViewB哄褒,UIViewB繼承于UIViewDUIViewC也繼承于UIViewD煌张;即 A->B->D呐赡,C->D

- (void)viewDidLoad {
    [super viewDidLoad];
    Class commonClass1 = [self commonClass1:[ViewA class] andClass:[ViewC class]];
    NSLog(@"%@",commonClass1);
    // 輸出:2018-03-22 17:36:01.868966+0800 兩個(gè)UIView的最近公共父類[84288:2458900] ViewD
}
// 獲取所有父類
- (NSArray *)superClasses:(Class)class {
    if (class == nil) {
        return @[];
    }
    NSMutableArray *result = [NSMutableArray array];
    while (class != nil) {
        [result addObject:class];
        class = [class superclass];
    }
    return [result copy];
}

- (Class)commonClass1:(Class)classA andClass:(Class)classB {
    NSArray *arr1 = [self superClasses:classA];
    NSArray *arr2 = [self superClasses:classB];
    for (NSUInteger i = 0; i < arr1.count; ++i) {
        Class targetClass = arr1[i];
        for (NSUInteger j = 0; j < arr2.count; ++j) {
            if (targetClass == arr2[j]) {
                return targetClass;
            }
        }
    }
    return nil;
}
  • 方法一明顯的是兩層for循環(huán),時(shí)間復(fù)雜度為 O(N^2)
    一個(gè)改進(jìn)的辦法:我們將一個(gè)路徑中的所有點(diǎn)先放進(jìn)NSSet中.因?yàn)镹SSet的內(nèi)部實(shí)現(xiàn)是一個(gè)hash表骏融,所以查詢元素的時(shí)間的復(fù)雜度變成 O(1),我們一共有N個(gè)節(jié)點(diǎn)链嘀,所以總時(shí)間復(fù)雜度優(yōu)化到了O(N)
- (Class)commonClass2:(Class)classA andClass:(Class)classB{
    NSArray *arr1 = [self superClasses:classA];
    NSArray *arr2 = [self superClasses:classB];
    NSSet *set = [NSSet setWithArray:arr2];
    for (NSUInteger i =0; i<arr1.count; ++i) {
        Class targetClass = arr1[i];
        if ([set containsObject:targetClass]) {
            return targetClass;
        }
    }
    return nil;
}

9.無序數(shù)組中的中位數(shù)(快排思想)

參考:求無序數(shù)組中的中位數(shù)

10.給定一個(gè)整數(shù)數(shù)組和一個(gè)目標(biāo)值萌狂,找出數(shù)組中和為目標(biāo)值的兩個(gè)數(shù)。

你可以假設(shè)每個(gè)輸入只對應(yīng)一種答案怀泊,且同樣的元素不能被重復(fù)利用茫藏。
示例:給定nums = [2, 7, 11, 15], target = 9 --- 返回 [0, 1]
思路:

  • 第一層for循環(huán)從索引0到倒數(shù)第二個(gè)索引拿到每個(gè)數(shù)組元素,
  • 第二個(gè)for循環(huán)遍歷上一層for循環(huán)拿到的元素的后面的所有元素霹琼。
  • 參考文章
class Solution {
    public int[] twoSum(int[] nums, int target) {
       int len = nums.length;
        int[] result = new int[2];
        for(int i = 0; i < len; i++){
            for(int j = i+1; j < len; j++){
                if(nums[i] + nums[j] == target){
                    result[0] = i;
                    result[1] = j; 
                    return result;
                }
            }
        }
        return result;
    }
}

分析:這個(gè)模塊是絕大部分開發(fā)人員的軟肋务傲!這個(gè)模塊是最能測試求職者思維能力的!但是我不建議面試官直接讓求職者手寫 在那樣的面試緊張環(huán)境枣申,手寫數(shù)據(jù)結(jié)構(gòu)或者一些算法代碼售葡,是非常有挑戰(zhàn)的!思維到我覺得差不多忠藤!

架構(gòu)設(shè)計(jì)

1:設(shè)計(jì)模式是為了解決什么問題的挟伙?

設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的模孩、經(jīng)過分類編目的像寒、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼瓜贾、讓代碼更容易被他人理解、保證代碼可靠性携悯。

設(shè)計(jì)模式最主要解決的問題是通過封裝和隔離變化點(diǎn)來處理軟件的各種變化問題祭芦。
隔離變化的好處在于,將系統(tǒng)中經(jīng)常變化的部分和穩(wěn)定的部分隔離憔鬼,有助于增加復(fù)用性龟劲,并降低系統(tǒng)耦合度。很多設(shè)計(jì)模式的意圖中都明顯地指出了其對問題的解決方案轴或,學(xué)習(xí)設(shè)計(jì)模式的要點(diǎn)是發(fā)現(xiàn)其解決方案中封裝的變化點(diǎn)昌跌。

三本經(jīng)典書籍:《GOF設(shè)計(jì)模式》《設(shè)計(jì)模式解析》照雁,《Head First Design Pattern》

設(shè)計(jì)模式是軟件開發(fā)領(lǐng)域的精髓之一蚕愤。學(xué)好設(shè)計(jì)模式是目前每一個(gè)開發(fā)人員的必修課,

2:看過哪些第三方框架的源碼饺蚊,它們是怎么設(shè)計(jì)的萍诱?

這個(gè)題目就看你個(gè)人的感觸,考量你平時(shí)的功底污呼!
大家可以針對性一些常見的框架:RxSwift裕坊、AlamofireMoya燕酷、AFNetworing籍凝、YYKit.... 掌握會用的同時(shí)周瞎,必須要掌握底層的核心思想!

3:可以說幾個(gè)重構(gòu)的技巧么饵蒂?你覺得重構(gòu)適合什么時(shí)候來做声诸?

  • 重復(fù)代碼的提煉
  • 冗長方法的分割
  • 嵌套條件分支的優(yōu)化
  • 去掉一次性的臨時(shí)變量
  • 消除過長參數(shù)列表
  • 提取類或繼承體系中的常量
  • 讓類提供應(yīng)該提供的方法
  • 拆分冗長的類
  • 提取繼承體系中重復(fù)的屬性與方法到父類

在新功能增加時(shí)候,在擴(kuò)展不再簡單的時(shí)候苹享。重構(gòu)是一個(gè)不斷的過程双絮。

4:開發(fā)中常用架構(gòu)設(shè)計(jì)模式你怎么選型?

這里也是一道開放性題目!并不是說某一種架構(gòu)就是最優(yōu)秀的~只有最合適的得问!根據(jù)公司情況囤攀,項(xiàng)目現(xiàn)狀,以及開發(fā)者水平及時(shí)調(diào)整宫纬,設(shè)計(jì)焚挠!

5:你是如何組件化解耦的?

iOS 解藕漓骚、組件化最常用的是使用統(tǒng)跳路由的方式蝌衔,目前比較常用的 iOS 開源路由框架主要是JLRoutesMGJRouter蝌蹂、HHRouter等噩斟,這些路由框架各有優(yōu)點(diǎn)和缺點(diǎn),基本可以滿足大部分需求孤个。目前最常用來作路由跳轉(zhuǎn)剃允,以實(shí)現(xiàn)基本的組件化開發(fā),實(shí)現(xiàn)各模塊之間的解藕齐鲤。但是斥废,在實(shí)際中開發(fā)中會發(fā)現(xiàn),無法徹底使用它們完成所有模塊間通信给郊,比如模塊間的同步牡肉、異步通信等。再比如淆九,我們在配置了相關(guān)路由跳轉(zhuǎn)的 URL 后统锤,如何在上線之后動(dòng)態(tài)修改相關(guān)跳轉(zhuǎn)邏輯?在模塊間通信時(shí)炭庙,如何在上線后動(dòng)態(tài)修改相關(guān)參數(shù)跪另?APP 能否實(shí)現(xiàn)類似 Web 的302跳轉(zhuǎn)學(xué)習(xí)參考

分析:架構(gòu)設(shè)計(jì)這一層對于一個(gè)iOS中高級開發(fā)人員來說煤搜。這一塊那是他必須要去思考和感受總結(jié)的!如果這位求職者開發(fā)4-5年了免绿,一直都在做應(yīng)用層界面開發(fā),那么想必他未來的職業(yè)晉升是已經(jīng)落后了的擦盾!面試官不妨在這一個(gè)模塊單獨(dú)設(shè)計(jì)成一面嘲驾,就和求職者一起交流討論淌哟。畢竟這些思維的設(shè)計(jì),也許能夠給面試官帶來一些不一樣的東西辽故!??

性能優(yōu)化

1:tableView 有什么好的性能優(yōu)化方案徒仓?

2: 界面卡頓和檢測你都是怎么處理?

3:談?wù)勀銓﹄x屏渲染的理解誊垢?

4:如何降低APP包的大小

5:日常如何檢查內(nèi)存泄露掉弛?

6:APP啟動(dòng)時(shí)間應(yīng)從哪些方面優(yōu)化?

分析:現(xiàn)在APP性能優(yōu)化已經(jīng)成為iOS中高級開發(fā)人員必須要去關(guān)系的東西喂走!這一塊我個(gè)人建議結(jié)合實(shí)際開發(fā)去和求職者交流殃饿。而不是僅僅停留在知識點(diǎn)問答,因?yàn)闆]有實(shí)際開發(fā)能力的性能優(yōu)化都只是紙上談兵芋肠!

總結(jié)

這一套面試題還是有一定的水平和難度的乎芳!但是對于要應(yīng)聘一份iOS中高級開發(fā)崗位,還是比較中肯的帖池!希望大家能夠在接下來的跳槽漲薪有自己的思想奈惑。

文章有長,建議關(guān)注備份睡汹,不管是正在面試還是即將面試肴甸,應(yīng)該對你有幫助!既然看到這里:麻煩點(diǎn)個(gè)贊吧囚巴!??

PS:對本文內(nèi)容存在疑問還望指出原在,謝謝!加油文兢,靜候你的佳音

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市焕檬,隨后出現(xiàn)的幾起案子姆坚,更是在濱河造成了極大的恐慌,老刑警劉巖实愚,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兼呵,死亡現(xiàn)場離奇詭異,居然都是意外死亡腊敲,警方通過查閱死者的電腦和手機(jī)击喂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碰辅,“玉大人懂昂,你說我怎么就攤上這事∶槐觯” “怎么了凌彬?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵沸柔,是天一觀的道長。 經(jīng)常有香客問我铲敛,道長褐澎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任伐蒋,我火速辦了婚禮工三,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘先鱼。我一直安慰自己俭正,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布型型。 她就那樣靜靜地躺著段审,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闹蒜。 梳的紋絲不亂的頭發(fā)上寺枉,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音绷落,去河邊找鬼姥闪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛砌烁,可吹牛的內(nèi)容都是我干的筐喳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼函喉,長吁一口氣:“原來是場噩夢啊……” “哼避归!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起管呵,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤梳毙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后捐下,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體账锹,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年坷襟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奸柬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡婴程,死狀恐怖廓奕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤懂从,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布授段,位于F島的核電站,受9級特大地震影響番甩,放射性物質(zhì)發(fā)生泄漏侵贵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一缘薛、第九天 我趴在偏房一處隱蔽的房頂上張望窍育。 院中可真熱鬧,春花似錦宴胧、人聲如沸漱抓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乞娄。三九已至,卻和暖如春显歧,著一層夾襖步出監(jiān)牢的瞬間仪或,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工士骤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留范删,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓拷肌,卻偏偏與公主長得像到旦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子巨缘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344