block(代碼塊) 1.1 什麼是block block是iOS中一種比較特殊的數據類型。(可以定義變數、做形參或返回值) block是蘋果官方特別推薦使用的數據類型,應用場景比較廣泛 動畫 多線程 集合遍歷 網路請求回調 動畫 多線程 集合遍歷 網路請求回調 在多線程和網路也使用得相當頻繁,一般 ...
block(代碼塊)
1.1 什麼是block
- block是iOS中一種比較特殊的數據類型。(可以定義變數、做形參或返回值)
- block是蘋果官方特別推薦使用的數據類型,應用場景比較廣泛
- 動畫
- 多線程
- 集合遍歷
- 網路請求回調
在多線程和網路也使用得相當頻繁,一般都是作為回調使用!
- block的作用
- 和函數一樣,用來保存某一段代碼,可以在恰當的時間再取出來調用
- block功能類似於函數(方法),比函數更強大。
- block是一種數據類型,可以嵌套定義,隨時調用。
Xcode輸入 inline 可快速生成(快捷鍵)
1.2 block的格式
- 比較函數、函數指針、block:
如果block沒有參數, 那麼^後面的()可以省略
- block案例
1.3 給block類型取別名(類比函數指針)
變數的名稱就是類型名稱(即別名)
1.4 block的應用場景
當前面代碼塊一樣,後面代碼塊一樣,中間的代碼塊不一樣,中間的代碼塊就用block。
1.5 block的註意事項
- block中可以定義和外界同名的變數,但是在block中訪問的是block中定義的變數(就近原則,和函數一樣)
- 在代碼塊中可以訪問外面的變數
(1)在代碼塊中可以直接訪問和修改非棧區的變數(使用的是同一個變數)
(2)棧區的變數可以訪問,但預設不能修改(使用的是不同的變數,實際上訪問的是自己拷貝的值)
block中的變數和外界的局部變數並不是同一個變數,block會將外界的變數拷貝一份到堆記憶體中
block中使用的外界變數是copy的,所以在調用之前修改外界變數的值,不會影響到block中copy的值
(3)在代碼塊中修改局部變數編譯不通過。怎麼在代碼塊中修改局部變數呢?在局部變數前面加上關鍵字:__block
1.6 面試題:block是存儲在堆中還是棧中?
- 預設情況下block存儲在棧中,如果對block進行一個copy操作,block會轉移到堆中
- 如果block在棧中, block中訪問了外界的對象, 那麼不會對對象進行retain操作
- 如果block在堆中, block中訪問了外界的對象, 那麼會對外界的對象進行一次retain
1.7 block的記憶體泄露體現
block在copy時都會對block內部用到的對象進行強引用(ARC)或者retainCount增1(非ARC)。
在ARC與非ARC環境下對block使用不當都會引起迴圈引用問題。
一般表現為:
某個類將block作為自己的屬性變數,然後該類在block的方法體裡面又使用了該類本身,簡單說就是
1)MRC情況下,用__block可以消除迴圈引用。
2)ARC情況下,必須用弱引用才可以解決迴圈引用問題,iOS5之後可以直接使用__weak,之前則只能使用__unsafe_unretained了,__unsafe_unretained缺點是指針釋放後自己不會置空。
什麼時候棧上的Block會複製到堆呢?
- 調用Block的copy實例方法時
- Block作為函數返回值返回時
- 將Block賦值給附有__strong修飾符、id類型的類或Block類型成員變數時
- 在方法名中含有usingBlock的Cocoa框架方法或GCD的API中傳遞Block時
block很多的用處是跨越兩個類來使用的。
實現兩個頁面之間的傳值:
- 通過“協議/代理”實現兩個頁面之間傳值
- 使用block作為property,實現兩個頁面之間傳值
面試題: