1. 程式人生 > >ios 面試題之—block

ios 面試題之—block

對block的綜合理解

block的實質

物件, 一個函式指標, 指向程式碼塊, 以及上下文所需的變數
函式指標和block的格式對比

函式指標 void(*fun)(int)
block void(^fun)(int)
block在記憶體中的分類

全域性block –> GlobalBlock <==> 相當於全域性變數, 系統會自動釋放
棧block –> StackBlock <==> 相當於區域性變數, 系統會自動釋放
堆block –> MallocBlock <==> (需要手動釋放記憶體)

block型別區分方法

如果block實現中沒有訪問任何”外部”變數(包括區域性和全域性), 該block為GlobalBlock
如果block實現中訪問了任何”外部”變數(包括區域性和全域性), 該block為StackBlock
對StackBlock進行拷貝(copy/Block_copy), 該block為MallocBlock
注意點:

block預設都是在棧上建立的, 當block超過作用域, 就會被銷燬, 如果要在作用域外使用block, 應copy該block到堆上, 此時會建立一個新的MallocBlock到堆上
宣告block物件, 應該使用copy修飾, 將其儲存到堆上, 不然在回撥時block已經銷燬, 無法訪問
delegate跟block的區別,使用場景有哪些不同?

定義:
A物件設定協議和代理,並讓B物件遵守協議和成為代理,從而讓B物件實現協議方法, 是為代理
block的本質是指標函式, 內部封存的是程式碼塊
區別:
代理

代理是一對一的, 需要設定介面
可能引起迴圈引用,導致記憶體洩漏
通過指定delegate物件為weak,可以避免迴圈引用
block

block的不需要設定介面, 使用更為輕型
更容易造成迴圈引用
通過指定block內的物件為__weak,可以避免迴圈引用
使用場景:

代理

當要實現的方法大於3個
為了防止迴圈引用時
寫一個庫給別人使用,又不清楚使用者的能力,建議使用delegate

block

當要實現的方法小於3個
需要請求資料回撥

GCD跟Block使用需要注意什麼?

GCD使用注意點:

防止死鎖

GCD不能控制最大任務併發量(無法決定具體開多少子執行緒,只能由系統決定)
GCD的請求一旦傳送,無法直接取消

Block使用注意點:

防止迴圈引用

在block中用到外部變數都是隻讀拷貝的
棧block超過作用域就被自動釋放了
堆block需要手動釋放

Block在ARC跟MRC中的行為和用法有什麼區別?

相同點

block的本質一樣, 都是函式指標
使用__block都可以解決在block中修改外部變數的問題

不同點

解決迴圈引用的方式不同
MRC中使用__block
ARC中使用 __weak
block用什麼屬性修飾,為什麼?

在MRC中, 定義Block屬性時, 應該用copy修飾
在ARC中, 定義Block屬性時, 系統會自動將其copy, 即複製到堆上. 但習慣上還是會用copy修飾
用copy修飾的原因
block建立時預設是建立在棧上的, 超過作用域後就會被銷燬, 只有使用copy才會生成一個堆block, 在作用域外被訪問