iOS 基礎(chǔ)知識(shí)概述

iOS 基礎(chǔ)知識(shí)概述

基本修飾屬性

  • assion
    -基本用于修飾基本數(shù)據(jù)類型 如 int 等 是弱引用
  • copy
    • copy 修飾不可變對(duì)象 和strong 修飾符 一樣對(duì)當(dāng)前的對(duì)象進(jìn)行一個(gè)強(qiáng)引用 copy 修飾可變對(duì)象 會(huì)對(duì)當(dāng)前對(duì)象 進(jìn)行深拷貝 生成一個(gè)不可變對(duì)象
    • 追問捌刮?用strong 修飾 會(huì)有什么問題 获诈?用strong 修飾可變對(duì)象 在某些可能會(huì)發(fā)生數(shù)據(jù)被修改風(fēng)險(xiǎn) 這個(gè)根據(jù)需求進(jìn)行判斷
    • 還可用用于對(duì)于block 進(jìn)行修飾 本質(zhì)意義要從棧上復(fù)制到堆上
    • 為什么 要把block 從棧上 復(fù)制到堆上旷余?延長(zhǎng)block的生命周期
  • strong
    • strong 是一個(gè)強(qiáng)引用 會(huì)對(duì)當(dāng)前對(duì)象保證在合適的生命周期不會(huì)銷毀
  • weak
    • weak 弱引用 不會(huì)增加引用計(jì)數(shù) 一般用于防止循環(huán)引用使用
  • notatomic
    • 非原子性 就不會(huì)保證線程讀寫安全
  • atomic
    • 原子性 在修飾對(duì)象時(shí) 會(huì)對(duì)當(dāng)前對(duì)象set 和 get 方法進(jìn)行加鎖 保存讀寫安全

weak 實(shí)現(xiàn)原理

  • 當(dāng)我們用weak 修飾對(duì)象時(shí) 會(huì)調(diào)用initWeak方法 判斷對(duì)象是否為nil 不為nil 初始化一個(gè)新的weak指針對(duì)象的地址 調(diào)用storeWeak方法 更新指針指向 創(chuàng)建對(duì)應(yīng)的弱引用表 釋放時(shí) 調(diào)用clearDeallocating 函數(shù) 會(huì)根據(jù)對(duì)象的地址獲取所有weak指針地址數(shù)組 猫十,然后遍歷這個(gè)數(shù)據(jù)把期中的數(shù)據(jù)設(shè)置為nil 最后把這個(gè)從數(shù)據(jù)從這個(gè)weak表中 清理對(duì)象記錄。
  • weak 相關(guān)問題

**Block **

  • 本質(zhì)是一個(gè)oc 對(duì)象
  • Block 變量截取
    • 自動(dòng)變量值被Block 截獲 只能執(zhí)行Block語(yǔ)法瞬間值盯桦。保存后就不能修改此值薯嗤。Block 中使用自動(dòng)變量后 在Block 的結(jié)構(gòu)體實(shí)例中重寫改自動(dòng)變量也不會(huì)改變?cè)冉孬@的自動(dòng)變量
  • 截獲對(duì)象
    • 而在ARC環(huán)境下豪墅,對(duì)于聲明為__block的外部對(duì)象,在block內(nèi)部會(huì)進(jìn)行retain铣口,以至于在block環(huán)境內(nèi)能安全的引用外部對(duì)象滤钱。對(duì)于沒有聲明__block的外部對(duì)象,在block中也會(huì)被retain脑题。

KVO和KVC 實(shí)現(xiàn)原理

  • 當(dāng)某個(gè)類的屬性對(duì)象第一次被觀察時(shí)件缸,系統(tǒng)就會(huì)在運(yùn)行期動(dòng)態(tài)地創(chuàng)建該類的一個(gè)派生類,在這個(gè)派生類中重寫基類中任何被觀察屬性的setter 方法叔遂。派生類在被重寫的setter方法內(nèi)實(shí)現(xiàn)真正的通知機(jī)制
    如果原類為ClassName他炊,那么生成的派生類名為NSKVONotifying_ClassName
    每個(gè)類對(duì)象中都有一個(gè)isa指針指向當(dāng)前類,當(dāng)一個(gè)類對(duì)象的第一次被觀察掏熬,那么系統(tǒng)會(huì)偷偷將isa指針指向動(dòng)態(tài)生成的派生類佑稠,從而在給被監(jiān)控屬性賦值時(shí)執(zhí)行的是派生類的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)用。
    補(bǔ)充:KVO的這套實(shí)現(xiàn)機(jī)制中蘋果還偷偷重寫了class方法誊薄,讓我們誤認(rèn)為還是使用的當(dāng)前類履恩,從而達(dá)到隱藏生成的派生類
  • kvc
    • KVC(key-Value coding) 鍵值編碼,指iOS開發(fā)中呢蔫,可以允許開發(fā)者通過Key名直接訪問對(duì)象的屬性切心,或者給對(duì)象的屬性賦值飒筑。不需要調(diào)用明確的存取方法,這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)訪問和修改對(duì)象的屬性绽昏,而不是在編譯時(shí)確定协屡。
    • 程序優(yōu)先調(diào)用setKey:屬性值方法,代碼通過setter方法完成設(shè)置全谤。注意肤晓,這里的key是指成員變量名,首字母大小寫要符合KVC的命名規(guī)范认然,下同
      如果沒有找到setName:方法补憾,KVC機(jī)制會(huì)檢查+(BOOL)accessInstanceVariablesDirectly方法有沒有返回YES,默認(rèn)返回的是YES卷员,如果你重寫了該方法讓其返回NO盈匾,那么在這一步KVC會(huì)執(zhí)行setValue: forUndefineKey:方法,不過一般不會(huì)這么做子刮。所以KVC機(jī)制會(huì)搜索該類里面有沒有名為_key的成員變量威酒,無(wú)論該變量是在.h,還是在.m文件里定義挺峡,也不論用什么樣的訪問修飾符葵孤,只要存在_key命名的變量,KVC都可以對(duì)該成員變量賦值橱赠。
      如果該類既沒有setKey:方法尤仍,也沒有_key成員變量,KVC機(jī)制會(huì)搜索_isKey的成員變量狭姨。
      同樣道理宰啦,如果該類沒有setKey:方法,也沒有_key和_isKey成員變量饼拍,KVC還會(huì)繼續(xù)搜索key和isKey的成員變量赡模,再給他們賦值。
      如果上面列出的方法或者成員變量都不存在师抄,系統(tǒng)將會(huì)執(zhí)行該對(duì)象的setValue:forUndefinedKey:方法漓柑,默認(rèn)是拋出異常。

runtime

對(duì)象:OC中的對(duì)象指向的是一個(gè)objc_object指針類型叨吮,typedef struct objc_object *id;從它的結(jié)構(gòu)體中可以看出辆布,它包括一個(gè)isa指針,指向的是這個(gè)對(duì)象的類對(duì)象,一個(gè)對(duì)象實(shí)例就是通過這個(gè)isa找到它自己的Class茶鉴,而這個(gè)Class中存儲(chǔ)的就是這個(gè)實(shí)例的方法列表锋玲、屬性列表、成員變量列表等相關(guān)信息的

類:在OC中的類是用Class來(lái)表示的涵叮,實(shí)際上它指向的是一個(gè)objc_class的指針類型惭蹂,typedef struct objc_class *Class

OC的Class類型包括如下數(shù)據(jù)(即:元數(shù)據(jù)metadata):super_class(父類類對(duì)象)伞插;name(類對(duì)象的名稱);version剿干、info(版本和相關(guān)信息)蜂怎;instance_size(實(shí)例內(nèi)存大心驴獭)置尔;ivars(實(shí)例變量列表);methodLists(方法列表)氢伟;cache(緩存)榜轿;protocols(實(shí)現(xiàn)的協(xié)議列表);

當(dāng)然也包括一個(gè)isa指針,這說(shuō)明Class也是一個(gè)對(duì)象類型朵锣,所以我們稱之為類對(duì)象谬盐,這里的isa指向的是元類對(duì)象(metaclass),元類中保存了創(chuàng)建類對(duì)象(Class)的類方法的全部信息诚些。

為什么要設(shè)計(jì)metaclass
類對(duì)象飞傀、元類對(duì)象能夠復(fù)用消息發(fā)送流程機(jī)制;
單一職責(zé)原則

為什么對(duì)象方法沒有保存的對(duì)象結(jié)構(gòu)體里诬烹,而是保存在類對(duì)象的結(jié)構(gòu)體里砸烦?
方法是每個(gè)對(duì)象互相可以共用的,如果每個(gè)對(duì)象都存儲(chǔ)一份方法列表太浪費(fèi)內(nèi)存绞吁,由于對(duì)象的isa是指向類對(duì)象的幢痘,當(dāng)調(diào)用的時(shí)候,直接去類對(duì)象中查找就行了家破⊙账担可以節(jié)約很多內(nèi)存空間的

class_ro_t 和 class_rw_t 的區(qū)別?
class_rw_t提供了運(yùn)行時(shí)對(duì)類拓展的能力汰聋,而class_ro_t存儲(chǔ)的大多是類在編譯時(shí)就已經(jīng)確定的信息门粪。二者都存有類的方法、屬性(成員變量)烹困、協(xié)議等信息玄妈,不過存儲(chǔ)它們的列表實(shí)現(xiàn)方式不同。簡(jiǎn)單的說(shuō)class_rw_t存儲(chǔ)列表使用的二維數(shù)組韭邓,class_ro_t使用的一維數(shù)組措近。 class_ro_t存儲(chǔ)于class_rw_t結(jié)構(gòu)體中,是不可改變的女淑。保存著類的在編譯時(shí)就已經(jīng)確定的信息瞭郑。而運(yùn)行時(shí)修改類的方法,屬性鸭你,協(xié)議等都存儲(chǔ)于class_rw_t中

category如何被加載的,兩個(gè)category的load方法的加載順序屈张,兩個(gè)category的同名方法的加載順序

+load 方法是 images 加載的時(shí)候調(diào)用擒权,假設(shè)有一個(gè) XXXClass 類,其主類和所有分類的 +load 都會(huì)被調(diào)用阁谆,優(yōu)先級(jí)是先調(diào)用主類碳抄,且如果主類有繼承鏈,那么加載順序還必須是基類的 +load 场绿,接著是父類剖效,最后是子類;category 的 +load 則是按照編譯順序來(lái)的焰盗,先編譯的先調(diào)用璧尸,后編譯的后調(diào)用,可在 Xcode 的 BuildPhase 中查看
分類添加到了 rw = cls->data() 中的 methods/properties/protocols 中熬拒,實(shí)際上并無(wú)覆蓋爷光,只是查找到就返回了,導(dǎo)致本類函數(shù)無(wú)法加載澎粟。

initialize && Load

類第一次被使用到的時(shí)候會(huì)被調(diào)用蛀序,底層實(shí)現(xiàn)有個(gè)邏輯先判斷父類是否被初始化過,沒有則先調(diào)用父類活烙,然后在調(diào)用當(dāng)前類的 initialize 方法.

一個(gè)類 A 存在多個(gè) category 徐裸,且 category中各自實(shí)現(xiàn)了 initialize 方法,這時(shí)候走的是 消息發(fā)送流程瓣颅,也就說(shuō) initialize 方法只會(huì)調(diào)用一次倦逐,也就是最后編譯的那個(gè)category中的 initialize 方法。
如果+load 方法中調(diào)用了其他類:比如 B 的某個(gè)方法宫补,其實(shí)就是走消息發(fā)送流程檬姥,由于 B 沒有初始化過,則會(huì)調(diào)用其 initialize 方法粉怕,但此刻 B 的 +load 方法可能還沒有被系統(tǒng)調(diào)用過健民。

方法查詢-> 動(dòng)態(tài)解析-> 消息轉(zhuǎn)發(fā)
【self test】會(huì)轉(zhuǎn)換成 objc_megsend方法 檢測(cè)當(dāng)前targte 是否為nil 如果為nil則忽略
- 不是 會(huì)從當(dāng)前對(duì)象 方法列表里面查找方法 如果找到了 就直接調(diào)用執(zhí)行 如果沒有找到就會(huì)去父類方法列表里面查找 如果還沒有找到 就根類方法列表查找 如果還沒有找到 就會(huì)走消息轉(zhuǎn)發(fā)流程
- 通過resolveInstanceMethod 得知方法是否動(dòng)態(tài)添加,YES則通過 class_addMethod 動(dòng)態(tài)添加方法贫贝,處理消息秉犹,否則進(jìn)入下一步、
- forwardingTargetForSelect 用于指定那個(gè)對(duì)象來(lái)響應(yīng)消息稚晚。如果返回nil 則進(jìn)入第三步
- methodSignatureForSelector 進(jìn)行方法簽名崇堵,可以將函數(shù)參數(shù)類型和返回值封裝。如果返回nil 說(shuō)明消息無(wú)法處理并報(bào)錯(cuò)
- 把 imp 指向_objc_msgForward函數(shù)指針 最后執(zhí)行這個(gè)IMP
runLoop

線程和 RunLoop 之間是一一對(duì)應(yīng)的客燕,其關(guān)系是保存在一個(gè)全局的 Dictionary 里鸳劳。線程剛創(chuàng)建時(shí)并沒有 RunLoop,如果你不主動(dòng)獲取也搓,那它一直都不會(huì)有赏廓。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時(shí)涵紊,RunLoop 的銷毀是發(fā)生在線程結(jié)束時(shí)。你只能在一個(gè)線程的內(nèi)部獲取其 RunLoop(主線程除外)幔摸。
mode
同時(shí)蘋果還提供了一個(gè)操作 Common 標(biāo)記的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes)摸柄,你可以用這個(gè)字符串來(lái)操作 Common Items,或標(biāo)記一個(gè) Mode 為 “Common”既忆。使用時(shí)注意區(qū)分這個(gè)字符串和其他 mode name驱负。

  1. kCFRunLoopDefaultMode: App的默認(rèn) Mode,通常主線程是在這個(gè) Mode 下運(yùn)行的尿贫。
  2. UITrackingRunLoopMode: 界面跟蹤 Mode电媳,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響庆亡。
  3. kCFRunLoopCommonModes: 這是一個(gè)占位的 Mode,沒有實(shí)際作用捞稿。

PerformSelecter
當(dāng)調(diào)用 NSObject 的 performSelecter:afterDelay: 后又谋,實(shí)際上其內(nèi)部會(huì)創(chuàng)建一個(gè) Timer 并添加到當(dāng)前線程的 RunLoop 中。所以如果當(dāng)前線程沒有 RunLoop娱局,則這個(gè)方法會(huì)失效彰亥。

當(dāng)調(diào)用 performSelector:onThread: 時(shí),實(shí)際上其會(huì)創(chuàng)建一個(gè) Timer 加到對(duì)應(yīng)的線程去衰齐,同樣的任斋,如果對(duì)應(yīng)線程沒有 RunLoop 該方法也會(huì)失效。

GCD

  • GCD中常用的函數(shù)有哪些及使用場(chǎng)景
    • dispatch_async 開啟一個(gè)異步的網(wǎng)絡(luò)請(qǐng)求
    • dispatch_after 簡(jiǎn)單的延遲執(zhí)行的方式
    • dispatch_once 只執(zhí)行一次的代碼 創(chuàng)建單例
    • dispatch_group 維護(hù)一些異步任務(wù)的同步問題
    • dispatch_barrier_async 文件的讀寫操作時(shí)使用耻涛,保證讀操作的準(zhǔn)確性废酷。另外,有一點(diǎn)需要注意抹缕,dispatch_barrier_sync和dispatch_barrier_async只在自己創(chuàng)建的并發(fā)隊(duì)列上有效澈蟆,在全局(Global)并發(fā)隊(duì)列、串行隊(duì)列上卓研,效果跟dispatch_(a)sync效果一樣趴俘。
    • dispatch_semaphore_signal
  • 同步、異步奏赘、串行寥闪、并行的區(qū)別
    • 同步 不開啟線程
    • 異步 開啟線程
    • 同步 串行 不開啟線程 按順序執(zhí)行
    • 異步 串行 開啟線程 按順序執(zhí)行
    • 同步 并行 不會(huì)新建線程 按順序執(zhí)行
    • 異步 并行 會(huì)開多條線程 操作無(wú)序
      11
    • dispatch_async(dispatch_get_main(), ^{})的實(shí)現(xiàn)原理
      - dispatch_async 指的是將指定的Block 異步的追加到指定的queue中 這個(gè)函數(shù)不做任何等待
      • dispatch_sync 將指定的block 同步追加到指定的queue 中在追加之后 dispatch——sync 會(huì)一直等待
    • performSelector:..afterDelay:的實(shí)現(xiàn)原理
      - 內(nèi)部會(huì)創(chuàng)建一個(gè)Timer 并添加到當(dāng)前線程的RunLoop 如果在子線程下 調(diào)用方法 是不會(huì)執(zhí)行的 子線程Runloop 默認(rèn)是不開啟的
    • runloop與線程的關(guān)系
      • 線程和Runloop 之間是一一對(duì)應(yīng)的,其關(guān)系是保存在一個(gè)全局的字典里磨淌。線程剛創(chuàng)建沒有Runloop 疲憋。Runloop 的創(chuàng)建是發(fā)生在第一次獲取時(shí) Runloop 的銷毀時(shí)發(fā)生在線程結(jié)束時(shí) 只能在一個(gè)線程內(nèi)部獲取其Runloop(主線程除外)

當(dāng)調(diào)用 dispatch_async(dispatch_get_main_queue(), block) 時(shí),libDispatch 會(huì)向主線程的 RunLoop 發(fā)送消息伦糯,RunLoop會(huì)被喚醒柜某,并從消息中取得這個(gè) block嗽元,并在回調(diào) CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE() 里執(zhí)行這個(gè) block。但這個(gè)邏輯僅限于 dispatch 到主線程喂击,dispatch 到其他線程仍然是由 libDispatch 處理的剂癌。

自動(dòng)釋放池(autoreleasepool)

Autorelease Pool 是由多個(gè) AutoreleasePoolPage 對(duì)象以雙向鏈表的方式組織起來(lái)的數(shù)據(jù)結(jié)構(gòu)。

每個(gè) AutoreleasePoolPage 只能存儲(chǔ)有限個(gè)對(duì)象指針翰绊。當(dāng)新的對(duì)象加入 Autorelease Pool 的時(shí)候佩谷,如果當(dāng)前的 AutoreleasePoolPage 存儲(chǔ)空間不夠,會(huì)新初始化一個(gè) AutoreleasePoolPage监嗜,加入到鏈表末端谐檀。

Autorelease Pool 可以被嵌套創(chuàng)建。創(chuàng)建一個(gè)新的 Autorelease Pool 的時(shí)候裁奇,會(huì)在當(dāng)前 AutoreleasePoolPage 中插入邊界對(duì)象 POOL_BOUNDARY桐猬,以和上一個(gè) Autorelease Pool 以區(qū)分。

當(dāng) Autorelease Pool 銷毀的時(shí)候刽肠,對(duì) AutoreleasePoolPage 里存儲(chǔ)的所有對(duì)象依次從后往前調(diào)用 release溃肪,直到遇到對(duì)象 POOL_BOUNDARY,表明當(dāng)前 Autorelease Pool 中的對(duì)象已經(jīng)被全部釋放音五。

App啟動(dòng)后惫撰,蘋果在主線程 RunLoop 里注冊(cè)了兩個(gè) Observer,其回調(diào)都是 _wrapRunLoopWithAutoreleasePoolHandler()躺涝。

第一個(gè) Observer 監(jiān)視的事件是 Entry(即將進(jìn)入Loop)厨钻,其回調(diào)內(nèi)會(huì)調(diào)用 _objc_autoreleasePoolPush() 創(chuàng)建自動(dòng)釋放池。其 order 是-2147483647坚嗜,優(yōu)先級(jí)最高夯膀,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前。

第二個(gè) Observer 監(jiān)視了兩個(gè)事件: BeforeWaiting(準(zhǔn)備進(jìn)入休眠) 時(shí)調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池惶傻;Exit(即將退出Loop) 時(shí)調(diào)用 _objc_autoreleasePoolPop() 來(lái)釋放自動(dòng)釋放池棍郎。這個(gè) Observer 的 order 是 2147483647,優(yōu)先級(jí)最低银室,保證其釋放池子發(fā)生在其他所有回調(diào)之后涂佃。

在主線程執(zhí)行的代碼,通常是寫在諸如事件回調(diào)蜈敢、Timer回調(diào)內(nèi)的辜荠。這些回調(diào)會(huì)被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著,所以不會(huì)出現(xiàn)內(nèi)存泄漏抓狭,開發(fā)者也不必顯示創(chuàng)建 Pool 了伯病。

Autoreleasepool是由多個(gè)AutoreleasePoolPage以雙向鏈表的形式連接起來(lái)的,

Autoreleasepool的基本原理:在每個(gè)自動(dòng)釋放池創(chuàng)建的時(shí)候,會(huì)在當(dāng)前的AutoreleasePoolPage中設(shè)置一個(gè)標(biāo)記位午笛,在此期間惭蟋,當(dāng)有對(duì)象調(diào)用autorelsease時(shí),會(huì)把對(duì)象添加到AutoreleasePoolPage中药磺,若當(dāng)前頁(yè)添加滿了告组,會(huì)初始化一個(gè)新頁(yè),然后用雙向量表鏈接起來(lái)癌佩,并把新初始化的這一頁(yè)設(shè)置為hotPage,當(dāng)自動(dòng)釋放池pop時(shí)木缝,從最下面依次往上pop,調(diào)用每個(gè)對(duì)象的release方法围辙,直到遇到標(biāo)志位我碟。 AutoreleasePoolPage結(jié)構(gòu)如下

class AutoreleasePoolPage {
magic_t const magic;
id *next;//下一個(gè)存放autorelease對(duì)象的地址
pthread_t const thread; //AutoreleasePoolPage 所在的線程
AutoreleasePoolPage * const parent;//父節(jié)點(diǎn)
AutoreleasePoolPage *child;//子節(jié)點(diǎn)
uint32_t const depth;//深度,也可以理解為當(dāng)前page在鏈表中的位置
uint32_t hiwat;
}

GCD

  • dispatch_sync 將任務(wù) block 通過 push 到隊(duì)列中,然后按照 FIFO 去執(zhí)行姚建。
  • dispatch_sync造成死鎖的主要原因是堵塞的tid和現(xiàn)在運(yùn)行的tid為同一個(gè)
  • dispatch_async 會(huì)把任務(wù)包裝并保存矫俺,之后就會(huì)開辟相應(yīng)線程去執(zhí)行已保存的任務(wù)。
  • semaphore 主要在底層維護(hù)一個(gè)value的值桥胞,使用 signal 進(jìn)行 + +1恳守,wait進(jìn)行-1。如果value的值大于或者等于0贩虾,則取消阻塞,否則根據(jù)timeout參數(shù)進(jìn)行超時(shí)判斷
  • dispatch_group 底層也是維護(hù)了一個(gè) value 的值沥阱,等待 group 完成實(shí)際上就是等待value恢復(fù)初始值缎罢。而notify的作用是將所有注冊(cè)的回調(diào)組裝成一個(gè)鏈表,在 dispatch_async 完成時(shí)判斷 value 是不是恢復(fù)初始值考杉,如果是則調(diào)用dispatch_async異步執(zhí)行所有注冊(cè)的回調(diào)策精。
  • dispatch_once 通過一個(gè)靜態(tài)變量來(lái)標(biāo)記 block 是否已被執(zhí)行,同時(shí)使用加鎖確保只有一個(gè)線程能執(zhí)行崇棠,執(zhí)行完 block 后會(huì)喚醒其他所有等待的線程咽袜。
    列舉你知道的線程同步策略?
    OSSpinLock 自旋鎖枕稀,已不再安全询刹,除了這個(gè)鎖之外,下面寫的鎖萎坷,在等待時(shí),都會(huì)進(jìn)入線程休眠狀態(tài),而非忙等
    os_unfair_lock atomic就是使用此鎖來(lái)保證原子性的
    pthread_mutex_t 互斥鎖义起,并且支持遞歸實(shí)現(xiàn)和條件實(shí)現(xiàn)
    NSLock,NSRecursiveLock,基本的互斥鎖淆两,NSRecursiveLock支持遞歸調(diào)用,都是對(duì)pthread_mutex_t的封裝
    NSCondition,NSConditionLock瓜浸,條件鎖澳淑,也都是對(duì)pthread_mutex_t的封裝
    dispatch_semaphore_t 信號(hào)量
    @synchronized 也是pthread_mutex_t的封裝
    有哪幾種鎖比原?各自的原理?它們之間的區(qū)別是什么杠巡?最好可以結(jié)合使用場(chǎng)景來(lái)說(shuō)
    自旋鎖:自旋鎖在無(wú)法進(jìn)行加鎖時(shí)量窘,會(huì)不斷的進(jìn)行嘗試,一般用于臨界區(qū)的執(zhí)行時(shí)間較短的場(chǎng)景忽孽,不過iOS的自旋鎖OSSpinLock不再安全绑改,主要原因發(fā)生在低優(yōu)先級(jí)線程拿到鎖時(shí),高優(yōu)先級(jí)線程進(jìn)入忙等(busy-wait)狀態(tài)兄一,消耗大量 CPU 時(shí)間厘线,從而導(dǎo)致低優(yōu)先級(jí)線程拿不到 CPU 時(shí)間,也就無(wú)法完成任務(wù)并釋放鎖出革。這種問題被稱為優(yōu)先級(jí)反轉(zhuǎn)造壮。
    互斥鎖:對(duì)于某一資源同時(shí)只允許有一個(gè)訪問,無(wú)論讀寫骂束,平常使用的NSLock就屬于互斥鎖
    讀寫鎖:對(duì)于某一資源同時(shí)只允許有一個(gè)寫訪問或者多個(gè)讀訪問耳璧,iOS中pthread_rwlock就是讀寫鎖
    條件鎖:在滿足某個(gè)條件的時(shí)候進(jìn)行加鎖或者解鎖,iOS中可使用NSConditionLock來(lái)實(shí)現(xiàn)
    遞歸鎖:可以被一個(gè)線程多次獲得展箱,而不會(huì)引起死鎖旨枯。它記錄了成功獲得鎖的次數(shù),每一次成功的獲得鎖混驰,必須有一個(gè)配套的釋放鎖和其對(duì)應(yīng)攀隔,這樣才不會(huì)引起死鎖。只有當(dāng)所有的鎖被釋放之后栖榨,其他線程才可以獲得鎖昆汹,iOS可使用NSRecursiveLock來(lái)實(shí)現(xiàn)

哪些場(chǎng)景可以觸發(fā)離屏渲染?(知道多少說(shuō)多少)
添加遮罩mask
添加陰影shadow
設(shè)置圓角并且設(shè)置masksToBounds為true
設(shè)置allowsGroupOpacity為true并且layer.opacity小于1.0和有子layer或者背景不為空
開啟光柵化shouldRasterize=true

響應(yīng)鏈
當(dāng)一個(gè)事件發(fā)生后婴栽,事件會(huì)從父控件傳給子控件满粗,也就是說(shuō)由UIApplication -> UIWindow -> UIView -> initial view,以上就是事件的傳遞,也就是尋找最合適的view的過程愚争。

2映皆、接下來(lái)是事件的響應(yīng)。首先看initial view能否處理這個(gè)事件准脂,如果不能則會(huì)將事件傳遞給其上級(jí)視圖(inital view的superView)劫扒;如果上級(jí)視圖仍然無(wú)法處理則會(huì)繼續(xù)往上傳遞;一直傳遞到視圖控制器view controller狸膏,首先判斷視圖控制器的根視圖view是否能處理此事件沟饥;如果不能則接著判斷該視圖控制器能否處理此事件,如果還是不能則繼續(xù)向上傳 遞;(對(duì)于第二個(gè)圖視圖控制器本身還在另一個(gè)視圖控制器中贤旷,則繼續(xù)交給父視圖控制器的根視圖广料,如果根視圖不能處理則交給父視圖控制器處理);一直到 window幼驶,如果window還是不能處理此事件則繼續(xù)交給application處理艾杏,如果最后application還是不能處理此事件則將其丟棄

MVC和MVVM的區(qū)別?MVVM和MVP的區(qū)別盅藻?
另一個(gè) MVP 與 MVC 之間的重大區(qū)別就是购桑,MVP(Passive View)中的視圖和模型是完全解耦的,它們對(duì)于對(duì)方的存在完全不知情氏淑,這也是區(qū)分 MVP 和 MVC 的一個(gè)比較容易的方法勃蜘。

無(wú)論是 MVVM 還是 Presentation Model,其中最重要的不是如何同步視圖和展示模型/視圖模型之間的狀態(tài)假残,是使用觀察者模式缭贡、雙向綁定還是其它的機(jī)制都不是整個(gè)模式中最重要的部分,最為關(guān)鍵的是展示模型/視圖模型創(chuàng)建了一個(gè)視圖的抽象辉懒,將視圖中的狀態(tài)和行為抽離出一個(gè)新的抽象阳惹,這才是 MVVM 和 PM 中需要注意的。

面向?qū)ο蟮膸讉€(gè)設(shè)計(jì)原則了解么眶俩?最好可以結(jié)合場(chǎng)景來(lái)說(shuō)莹汤。
對(duì)于設(shè)計(jì)模式的六大設(shè)計(jì)原則,單一職責(zé)原則主要說(shuō)明類的職責(zé)要單一颠印;里氏替換原則強(qiáng)調(diào)不要破壞繼承體系体啰;依賴倒置原則描述要面向接口編程;接口隔離原則講解設(shè)計(jì)接口的時(shí)候要精簡(jiǎn)嗽仪;迪米特法則告訴我們要降低耦合;開閉原則講述的是對(duì)擴(kuò)展開放柒莉,對(duì)修改關(guān)閉闻坚。

可以說(shuō)幾個(gè)重構(gòu)的技巧么?你覺得重構(gòu)適合什么時(shí)候來(lái)做兢孝?

了解編譯的過程么窿凤?分為哪幾個(gè)步驟?
預(yù)編譯:主要處理以“#”開始的預(yù)編譯指令跨蟹。
編譯:
詞法分析:將字符序列分割成一系列的記號(hào)雳殊。
語(yǔ)法分析:根據(jù)產(chǎn)生的記號(hào)進(jìn)行語(yǔ)法分析生成語(yǔ)法樹。
語(yǔ)義分析:分析語(yǔ)法樹的語(yǔ)義窗轩,進(jìn)行類型的匹配夯秃、轉(zhuǎn)換、標(biāo)識(shí)等。
中間代碼生成:源碼級(jí)優(yōu)化器將語(yǔ)法樹轉(zhuǎn)換成中間代碼仓洼,然后進(jìn)行源碼級(jí)優(yōu)化介陶,比如把 1+2 優(yōu)化為 3。中間代碼使得編譯器被分為前端和后端色建,不同的平臺(tái)可以利用不同的編譯器后端將中間代碼轉(zhuǎn)換為機(jī)器代碼哺呜,實(shí)現(xiàn)跨平臺(tái)。
目標(biāo)代碼生成:此后的過程屬于編譯器后端箕戳,代碼生成器將中間代碼轉(zhuǎn)換成目標(biāo)代碼(匯編代碼)某残,其后目標(biāo)代碼優(yōu)化器對(duì)目標(biāo)代碼進(jìn)行優(yōu)化,比如調(diào)整尋址方式陵吸、使用位移代替乘法玻墅、刪除多余指令、調(diào)整指令順序等走越。
匯編:匯編器將匯編代碼轉(zhuǎn)變成機(jī)器指令椭豫。
靜態(tài)鏈接:鏈接器將各個(gè)已經(jīng)編譯成機(jī)器指令的目標(biāo)文件鏈接起來(lái),經(jīng)過重定位過后輸出一個(gè)可執(zhí)行文件旨指。
裝載:裝載可執(zhí)行文件赏酥、裝載其依賴的共享對(duì)象。
動(dòng)態(tài)鏈接:動(dòng)態(tài)鏈接器將可執(zhí)行文件和共享對(duì)象中需要重定位的位置進(jìn)行修正谆构。
最后裸扶,進(jìn)程的控制權(quán)轉(zhuǎn)交給程序入口,程序終于運(yùn)行起來(lái)了搬素。

靜態(tài)鏈接了解么呵晨?靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的區(qū)別?
靜態(tài)庫(kù):鏈接時(shí)完整地拷貝至可執(zhí)行文件中熬尺,被多次使用就有多份冗余拷貝摸屠。

動(dòng)態(tài)庫(kù):鏈接時(shí)不復(fù)制,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存粱哼,供程序調(diào)用季二,系統(tǒng)只加載一次,多個(gè)程序共用揭措,節(jié)省內(nèi)存胯舷。

內(nèi)存的幾大區(qū)域,各自的職能分別是什么绊含?

棧區(qū):有系統(tǒng)自動(dòng)分配并釋放桑嘶,一般存放函數(shù)的參數(shù)值,局部變量等
堆區(qū):有程序員分配和釋放躬充,若程序員未釋放逃顶,則在程序結(jié)束時(shí)有系統(tǒng)釋放讨便,在iOS里創(chuàng)建出來(lái)的對(duì)象會(huì)放在堆區(qū)
數(shù)據(jù)段:字符串常量,全局變量口蝠,靜態(tài)變量
代碼段:編譯之后的代碼

TCP為什么要三次握手器钟,四次揮手?

HTTPS是如何實(shí)現(xiàn)驗(yàn)證身份和驗(yàn)證完整性的妙蔗?

使用數(shù)字證書和CA來(lái)驗(yàn)證身份,首先服務(wù)端先向CA機(jī)構(gòu)去申請(qǐng)證書傲霸,CA審核之后會(huì)給一個(gè)數(shù)字證書,里面包裹公鑰眉反、簽名昙啄、有效期,用戶信息等各種信息寸五,在客戶端發(fā)送請(qǐng)求時(shí)梳凛,服務(wù)端會(huì)把數(shù)字證書發(fā)給客戶端,然后客戶端會(huì)通過信任鏈來(lái)驗(yàn)證數(shù)字證書是否是有效的梳杏,來(lái)驗(yàn)證服務(wù)端的身份韧拒。

使用摘要算法來(lái)驗(yàn)證完整性,也就是說(shuō)在發(fā)送消息時(shí)十性,會(huì)對(duì)消息的內(nèi)容通過摘要算法生成一段摘要叛溢,在收到收到消息時(shí)也使用同樣的算法生成摘要,來(lái)判斷摘要是否一致劲适。

tabView的優(yōu)化

  • TableViewCell 復(fù)用 在cellForRowAtIndexPath:回調(diào)的時(shí)候只創(chuàng)建實(shí)例楷掉,快速返回cell,不綁定數(shù)據(jù)霞势。在willDisplayCell: forRowAtIndexPath:的時(shí)候綁定數(shù)據(jù)(賦值)烹植。
  • 高度緩存 UITableView-FDTemplateLayoutCell
  • 減少多余的繪制操作 盡可能將多張圖片合成為一張進(jìn)行顯示。 優(yōu)化圖片大小愕贡,盡量不要?jiǎng)討B(tài)縮放(contentMode)草雕。
  • 減少離屏渲染 觸發(fā)離屏渲染: layer.shouldRasterize,光柵化 layer.mask固以,遮罩 layer.allowsGroupOpacity為YES促绵,layer.opacity的值小于1.0 layer.cornerRadius,并且設(shè)置layer.masksToBounds為YES嘴纺。可以使用剪切過的圖片浓冒,或者使用layer畫來(lái)解決栽渴。
  • 離屏渲染的優(yōu)化建議
    使用ShadowPath指定layer陰影效果路徑。
    使用異步進(jìn)行l(wèi)ayer渲染(Facebook開源的異步繪制框架AsyncDisplayKit)稳懒。
    設(shè)置layer的opaque值為YES闲擦,減少?gòu)?fù)雜圖層合成慢味。
    盡量使用不包含透明(alpha)通道的圖片資源。
    盡量設(shè)置layer的大小值為整形值墅冷。
    直接讓美工把圖片切成圓角進(jìn)行顯示纯路,這是效率最高的一種方案。
    很多情況下用戶上傳圖片進(jìn)行顯示寞忿,可以在客戶端處理圓角驰唬。
    使用代碼手動(dòng)生成圓角image設(shè)置到要顯示的View上,利用UIBezierPath(Core Graphics框架)畫出來(lái)圓角圖片腔彰。
  • 異步渲染
  • 按需加載
    利用runloop提高滑動(dòng)流暢性叫编,在滑動(dòng)停止的時(shí)候再加載內(nèi)容,像那種一閃而過的(快速滑動(dòng))霹抛,就沒有必要加載搓逾,可以使用默認(rèn)的占位符填充內(nèi)容。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杯拐,一起剝皮案震驚了整個(gè)濱河市霞篡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌端逼,老刑警劉巖朗兵,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異裳食,居然都是意外死亡矛市,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門诲祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)浊吏,“玉大人,你說(shuō)我怎么就攤上這事救氯≌姨铮” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵着憨,是天一觀的道長(zhǎng)墩衙。 經(jīng)常有香客問我,道長(zhǎng)甲抖,這世上最難降的妖魔是什么漆改? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮准谚,結(jié)果婚禮上挫剑,老公的妹妹穿的比我還像新娘。我一直安慰自己柱衔,他們只是感情好樊破,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布愉棱。 她就那樣靜靜地躺著,像睡著了一般哲戚。 火紅的嫁衣襯著肌膚如雪奔滑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天顺少,我揣著相機(jī)與錄音朋其,去河邊找鬼。 笑死祈纯,一個(gè)胖子當(dāng)著我的面吹牛令宿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腕窥,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼粒没,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了簇爆?” 一聲冷哼從身側(cè)響起癞松,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎入蛆,沒想到半個(gè)月后响蓉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哨毁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年枫甲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扼褪。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡想幻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出话浇,到底是詐尸還是另有隱情脏毯,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布幔崖,位于F島的核電站食店,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赏寇。R本人自食惡果不足惜吉嫩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗅定。 院中可真熱鬧率挣,春花似錦、人聲如沸露戒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)智什。三九已至动漾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荠锭,已是汗流浹背旱眯。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留证九,地道東北人删豺。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像愧怜,于是被迫代替她去往敵國(guó)和親呀页。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容