精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

iOS 開發—探秘 Block 原理

移動開發 iOS
很多block原理性的文章都比較老,里面講的一些知識已經過時,這里用新版的iOS SDK再梳理一遍block原理,也是和大家一起對已有知識做一次復習。

1.概述

在iOS開發中,block大家用的都很熟悉了,是iOS開發中閉包的一種實現方式,可以對一段代碼邏輯進行封裝,使其可以像數據一樣被傳遞、存儲、調用,并且可以保存相關的上下文狀態。

很多block原理性的文章都比較老,里面講的一些知識已經過時,這里用新版的iOS SDK再梳理一遍block原理,也是和大家一起對已有知識做一次復習。

2.內存布局

block本質上可以理解為結構體,對于結構體的內存布局,先用一張圖來表示一下,圖中字段順序按照布局的先后順序:

  • isa:block也有isa,從內存結構上也屬于對象,isa指向的是block的類對象,類對象例如__NSMallocBlock__,后續文章會講到;
  • flags:用于存儲一些標志位信息,例如是否捕獲外部變量;
  • reserved:系統保留字段,后續可能會用于一些編譯優化標志位,或者存儲一些臨時變量的處理;
  • invoke:函數指針,指向了block要執行的函數地址,也就是block代碼塊對應的函數地址;
  • descriptor(現在叫desc):指向block_desc_0,包含block大小、捕獲的外部變量布局信息、增加引用計數和銷毀的相關函數指針;
  • variables:block捕獲的外部變量。

圖片圖片

3.類型

由于block也是對象,可以通過class方法獲取到其類型,也就是類對象。block有下面三種類型:

  • __NSGlobalBlock__,沒有訪問auto變量的block,訪問static變量是沒問題的。這種類型的變量并沒有什么意義,如果不需要用到auto變量,寫成方法就可以滿足需求;
  • __NSStackBlock__,在MRC環境下,訪問了auto變量,會默認被放在棧區。需要手動copy到堆區,ARC環境下會在訪問auto變量后,會自動拷貝到堆區;
  • __NSMallocBlock__,由開發者自己管理內存,不會由系統來釋放。

block的分配主要是在三個區域,堆區、棧區、全局區,全局區的數據存儲在數據段。

block在不同的場景會存在不同的內存區域中,在MRC中創建一個block首先是在__NSStackBlock__內存中的,然后我們使用copy方法將block拷貝到__NSMallocBlock__內存中進行內存管理。后來在ARC中系統已經幫我們做好了copy的操作,創建的block會自動copy到__NSMallocBlock__內存中,堆區的block也有引用計數的概念。如果這個block中沒有用到任何外部參數,系統會將這個block存放在__NSGlobalBlock__內存中。

圖片圖片

并且block也有繼承關系,以下面TestBlock的實例來說,其父類是__NSGlobalBlock__,所有block的父類是NSBlock,并且NSBlock繼承自NSObject類。在更早一些的iOS系統中,__NSGlobalBlock__和NSBlock之間,還會有一層__NSGlobalBlock的關系(后面沒有下劃線)。

圖片圖片

4.轉換C++

下面,我們通過clang命令將block轉為結構體,來分析下其具體實現。雖然這并不是最終運行在iOS系統上的代碼,其等于一種中間表現形式,后續編譯鏈接優化才會形成運行在手機上的ipa包,但對于我們了解block的實現原理有很大幫助。

4.1轉換命令

xcrun是Xcode用于查找和執行相關命令行的工具集,可以更好的執行clang命令,減少報錯。

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc [源文件路徑] -o [目標文件路徑]

clang命令有下面這些關鍵參數:

  • -fobjc-arc:如果項目是ARC或者ARC和MRC混編的環境,需要通過此參數修飾,表示按ARC的方式進行轉換,如果不需要ARC環境可以忽略;
  • -x objective-c++:此參數上面沒用,如果包含Objective++源文件的時候,需要用到此參數,以確保clang可以區分OC和C++代碼;
  • -rewrite-objc:告訴clang以C++的方式重寫出來,包含的上層代碼,clang會以底層代碼的方式進行展現;
  • [目標文件路徑]:非必傳參數,不傳的話默認在當前目錄生成一個同名的cpp文件,例如main.m對應main.cpp。

4.2轉換示例

下面在main.m中實現了一個很簡單的block,并且沒有捕獲任何外部變量,通過clang命令查看C++代碼,觀察block的具體實現原理。

圖片圖片

轉換后將C++源文件拉到最下面,可以看到main函數以及TestBlock的實現,main函數中有很多轉義代碼,刪掉后梳理邏輯會更清晰。

圖片圖片

5.結構體

5.1基礎結構

轉換后的代碼看著比較復雜,但我們只看關鍵信息,__main_block_impl_0構造函數也可以去掉,整理后就是下面三個結構體。在不包含外部變量和__block的前提下,block結構體各個字段就這么簡單,關鍵就是isa、Block_size、FuncPtr這三個。

圖片圖片

我們也可以打印block結構體相關字段,但由于block的結構體并沒有聲明在某個.h文件中,所以需要我們講clang轉換后的結構體粘到對應的文件中,做顯示聲明。隨后用__bridge的方式,將block對象橋接為自己聲明的結構體,即可打印對應字段。

圖片圖片

結構體中impl.FuncPtr存儲的就是回調函數地址,從地址可以看出是一個虛擬地址,block結構體都存儲在堆區。

圖片圖片

5.2調用部分

看完block結構體的定義,我們來到main函數中,看block的實現和調用轉換后是什么樣的。將main函數中block相關的轉換都去掉,結果如紅圈部分。本質上就是兩步,第一步是調用__main_block_impl_0的結構體構造函數,第二步是調用結構體的函數指針。

圖片圖片

第一行main函數中調用的構造方法,是__main_block_impl_0結構體聲明的C++構造函數,因為我們創建的是一個最簡單block,可以看到block的存儲區域是在stack棧區的。即main函數調用完,block生命周期就會結束。

圖片圖片

__main_block_impl_0構造函數有兩個參數,第一個紅圈部分就是傳入函數指針地址,函數對應的就是block內部的實現代碼。第二個參數是__main_block_desc_0_DATA結構體,其定義為__main_block_desc_0,并且默認實現第一個參數傳0,第二個參數是block結構體的大小,結構體為__main_block_impl_0 block自身的結構體大小。第三個參數有默認值,可以不傳。

圖片圖片

__main_block_desc_0結構體是一種緊湊型的寫法,在聲明__main_block_desc_0結構體后,緊接著聲明了一個名為__main_block_desc_0_DATA的變量,變量類型為靜態變量,并且實現了初始化相關代碼。

圖片圖片

在執行block的代碼位置,可以看到并不是block->impl.FuncPtr的方式調用,而是直接block->FuncPtr的方式調用,中間少了一步。

嚴謹些來說應該加上impl,但不加也不會出問題。這是因為,如果看未刪除轉換代碼的原始clang代碼,可以看到block是被轉換為__block_impl的,也就是說被當做__block_impl看待的。如果再結合__main_block_impl_0的結構體定義來看,__block_impl在成員變量的第一位,所以訪問FuncPtr是沒有問題的,只要不訪問Desc就是可以的。

6.外部變量

6.1值類型

如果在block的調用中加一個外部變量,那結構體將會是怎樣的?

圖片圖片

通過clang命令可以可以看到,轉換后的__main_block_impl_0中增加了一個同名字段,這很簡單沒必要過多解釋。在__main_block_impl_0構造函數中傳入,通過冒號后的初始化列表對value參數進行初始化。

圖片圖片

后面傳參和使用,就都是結構體賦值和取值邏輯,很簡單。

圖片圖片

6.2值傳遞

下面這種寫法,在block的使用中很容易踩坑。在block中使用value參數,并且打印value參數,發現結果為1,而不是2。

圖片圖片

通過C++源碼我們可以看到,這是因為如果block引用的外部變量是值類型,會采取直接復制值的方式,而不是指針引用。

圖片圖片

想解決這個問題也很簡單,通過__block修飾一下值類型,即可實現block內value的值和外部value參數統一。

圖片圖片

6.3靜態變量

我們看一下,如果捕獲的是一個static修飾的靜態變量,其結構體會是什么實現。

圖片圖片

轉換為C++代碼后,可以看到原來的值傳遞變成了地址傳遞,__main_block_impl_0中value的引用是指針引用,在main函數中將value的地址傳入。如果被static修飾的本身就是一個對象,對象是通過指針引用的,在block的結構體中就是兩個星號引用。也就是NSObject **obj。

圖片圖片

正是由于靜態變量地址傳遞的實現,在block內可以對靜態變量直接進行更改,而無需用__block進行修飾。

圖片圖片

6.4全局變量

如果把value改為全局變量,結構體會有什么變化呢?

圖片圖片

因為全局變量的作用域很大,所以并不需要block進行單獨持有即可訪問,結構體并不會新增字段。

圖片圖片

6.5對象類型變量

如果block中引用的是對象,而不是基礎數據類型,結構體會是什么定義呢?

圖片圖片

執行clang命令,執行完成后結構體是下圖的,下面代碼去掉了轉換,以及整理過代碼。可以看到多了兩個函數指針,__main_block_copy_0和__main_block_dispose_0。

以copy的實現__main_block_copy_0為例,執行后會調用Block_object_assign的實現,在實現中系統會根據person的引用方式,__strong、__weak、__unsafe_unretained,是強引用還是弱引用,調用對應的內存管理方法。

__main_block_dispose_0函數在block從堆區移除的時候被調用,調用dispose時會調用實現Block_object_dispose函數,函數中會根據person的引用方式,進行對應的減少引用計數或釋放操作。

copy和dispose兩個函數都有一個3的參數,這個參數是一個標志位,表示外部變量類型。這里是BLOCK_FIELD_IS_OBJECT表示一個對象類型,也有BLOCK_FIELD_IS_WEAK表示weak引用的變量,BLOCK_FIELD_IS_BLOCK表示block類型的變量等。

圖片圖片


責任編輯:武曉燕 來源: 搜狐技術產品
相關推薦

2013-06-04 15:41:31

iOS開發移動開發block

2009-06-15 15:57:21

Spring工作原理

2017-03-07 09:45:43

iOSBlock開發

2023-06-07 15:25:19

Kafka版本日志

2025-02-08 08:10:00

2013-07-19 12:52:50

iOS中BlockiOS開發學習

2024-02-27 22:31:00

Feign動態代理核心

2023-02-22 07:04:05

自動機原理優化實踐

2011-08-08 18:11:45

IOS 4Block UIActionShe

2009-11-04 15:54:20

Portlet入門企業門戶

2010-08-09 08:48:46

File APIWeb

2009-11-06 16:10:54

ClosureJavaScript開Google

2010-02-26 17:54:54

python

2010-08-27 10:41:41

iPhone核心應用程序

2014-03-07 13:23:23

百度面試iOS

2009-08-25 13:48:01

Java EE架構企業級應用

2013-07-19 14:00:13

iOS中BlockiOS開發學習

2013-07-19 14:35:59

iOS中BlockiOS開發學習

2011-06-28 10:42:38

Windows 8開發部門DevX

2013-04-17 10:06:55

Google GlasMirror API
點贊
收藏

51CTO技術棧公眾號

欧美在线视频一区二区| 亚洲国产精品va在线观看黑人| 亚洲精品第一区二区三区| 在线观看国产小视频| 欧美伊人久久| 日韩精品在线第一页| 91欧美视频在线| 欧美极品少妇videossex| 91在线观看一区二区| 国产成人精品免费视频| 欧美日韩精品亚洲精品| 欧美成人基地| 欧美一区二区三区视频在线观看| 成人黄色av片| 日韩大片在线永久免费观看网站| 成人av免费在线播放| 国产精品偷伦一区二区| 黄色激情视频在线观看| 日韩黄色大片| 亚洲精品美女视频| 亚洲欧美日韩一二三区| 在线看片福利| 亚洲一区二区在线免费观看视频| 欧美重口乱码一区二区| 狠狠躁夜夜躁av无码中文幕| 男女男精品视频网| 26uuu亚洲伊人春色| 农村黄色一级片| 久久亚洲在线| 亚洲天堂开心观看| 影音先锋人妻啪啪av资源网站| 不卡的国产精品| 在线免费不卡视频| 亚洲 高清 成人 动漫| 七七成人影院| 亚洲欧美激情在线| 亚洲欧美精品| www日韩tube| 91麻豆123| 久久精品国产理论片免费 | 91精品国产aⅴ一区二区| 色一情一乱一伦一区二区三区日本| 爱福利在线视频| 亚洲免费观看高清完整版在线观看熊| 亚洲高清在线播放| 韩日视频在线| 国产亚洲欧美中文| 欧美午夜欧美| 能在线看的av| 久久久久久夜精品精品免费| 久久av一区二区| 四虎免费在线观看| 国产老肥熟一区二区三区| 国产在线播放91| 一本一道人人妻人人妻αv| 青青草伊人久久| 国产精品日韩在线| 自拍偷拍精品视频| 美国毛片一区二区| 91精品国产自产在线老师啪| 亚洲系列在线观看| 黄色日韩网站视频| 91原创国产| 日本精品一区二区在线观看| 不卡的av电影在线观看| 精品日本一区二区三区在线观看| 无码精品人妻一区二区三区影院| 97se亚洲国产综合自在线不卡| 极品尤物一区二区三区| 男男激情在线| 亚洲国产精品高清| 熟女视频一区二区三区| 日本成人不卡| 欧美日韩国产中字| 一区二区三区免费播放| 国产95亚洲| 精品国产乱码久久久久久牛牛| 水蜜桃av无码| 精品免费av| 另类图片亚洲另类| 久草国产精品视频| 奇米综合一区二区三区精品视频| 成人夜晚看av| 蜜桃视频污在线观看| 2020国产精品久久精品美国| 亚洲精品一卡二卡三卡四卡| caopen在线视频| 精品成人久久av| 日日噜噜夜夜狠狠| 亚洲午夜免费| 亚洲午夜精品久久久久久久久久久久| 国产黄色录像片| 亚洲国产影院| 国产精品综合久久久| 亚洲av色香蕉一区二区三区| 久久久亚洲午夜电影| eeuss中文| 这里有精品可以观看| 欧美日韩国产大片| 亚洲男人在线天堂| 99re6这里只有精品| 午夜精品久久久久久99热软件| 中文字幕免费高清网站| 国产东北露脸精品视频| 视频一区三区| av中文在线资源| 欧美疯狂做受xxxx富婆| 国产三级国产精品| 欧美日韩ab| 国产精品久久久久久久久久久久| 成人午夜免费福利| 日本一区二区成人| 日韩视频第二页| 亚洲91网站| 日韩最新中文字幕电影免费看| 日本一区二区不卡在线| 狠狠色丁香九九婷婷综合五月| 蜜桃视频在线观看成人| 久草在线资源站资源站| 欧美高清视频一二三区| 亚洲人成人无码网www国产| 国产一区日韩欧美| 91在线观看免费网站| 国产大片在线免费观看| 欧美日韩在线看| 动漫av在线免费观看| 日韩一区三区| 日韩免费中文字幕| 青青操视频在线| 亚洲成av人片一区二区三区| 欧美精品色视频| 999视频精品| 国产日韩一区在线| 爱爱爱免费视频在线观看| 欧美午夜视频一区二区| xxxwww国产| 在线成人亚洲| 国产欧美在线一区二区| 青青草原av在线| 日韩欧美亚洲一区二区| 久久久精品视频免费观看| 久久国产精品99精品国产| 亚洲欧美日韩国产yyy| 香蕉视频亚洲一级| 亚洲人高潮女人毛茸茸| www.色国产| 久久久久久久久久久久久夜| 久久久免费视频网站| 日韩大片在线免费观看| 2019中文字幕免费视频| 日本一区高清| 欧美亚洲日本一区| 18精品爽国产三级网站| 男人的天堂久久精品| 亚洲一二区在线| 青青国产精品| 久久手机免费视频| 亚洲AV午夜精品| 亚洲国产精品视频| 国产ts丝袜人妖系列视频| 国产精品日韩欧美一区| 欧美一区视久久| 成人国产激情| 久久艹在线视频| 免费成人在线看| 欧美日韩在线免费| 免费91在线观看| 国产一区二区三区黄视频 | 一本一道久久综合狠狠老精东影业| 国产一区二区精品在线| 亚洲美女尤物影院| 色悠悠久久久久| 国产乱淫片视频| 香港成人在线视频| 韩国三级hd中文字幕| 精品在线观看免费| 激情五月婷婷六月| 蜜桃一区二区| 成人精品视频99在线观看免费| 羞羞的视频在线看| 亚洲男人天堂网站| 国产精品久久久午夜夜伦鲁鲁| 亚洲一区二区三区四区五区黄| 中文字幕免费在线播放| 男女男精品网站| www.av蜜桃| 国产一区二区三区不卡视频网站| 国产精品网站大全| 爱啪啪综合导航| 色噜噜狠狠狠综合曰曰曰88av| 精品国自产拍在线观看| 欧美午夜片欧美片在线观看| 在线观看亚洲网站| 99久久免费精品高清特色大片| 另类小说色综合| 伊人成人网在线看| 在线不卡日本| 亚洲春色h网| 亚洲综合第一页| 欧美人体一区二区三区| 九九精品在线视频| 国产视频三级在线观看播放| 欧美成人aa大片| 亚洲熟妇无码久久精品| 午夜精品在线视频一区| 翔田千里88av中文字幕| 91理论电影在线观看| 永久看看免费大片| 美女视频一区二区三区| 免费 成 人 黄 色| 中文字幕日韩欧美精品高清在线| 蜜桃精品久久久久久久免费影院| 白嫩亚洲一区二区三区| 国产精品久久久久久久av电影| 成人三级高清视频在线看| 久久亚洲国产成人| melody高清在线观看| 日韩激情视频在线| 亚洲精品国产精| 欧美日韩国产高清一区二区| 亚洲精品毛片一区二区三区| 精品毛片网大全| 青青草精品在线视频| 国产精品福利一区二区| a天堂中文字幕| 97超碰欧美中文字幕| 一边摸一边做爽的视频17国产| 精品一区二区三区香蕉蜜桃| 尤蜜粉嫩av国产一区二区三区| 亚洲作爱视频| 国产二区视频在线播放| 亚洲日本欧美| 给我免费播放片在线观看| 欧美日韩1区2区3区| 97久久国产亚洲精品超碰热| 91精品观看| 亚洲国产精品女人| 久久精品亚洲欧美日韩精品中文字幕| 日韩欧美亚洲精品| 九九视频免费观看视频精品| 久久综合婷婷综合| 婷婷亚洲成人| 精品日本一区二区三区| 色狠狠久久av综合| 精选一区二区三区四区五区| 老司机凹凸av亚洲导航| 国产美女99p| 欧美黑白配在线| 久久影院理伦片| 国产成人1区| 日韩成人av网站| 日韩欧美伦理| 制服国产精品| 欧美影院一区| 国产真人做爰毛片视频直播| 影音先锋在线一区| 日韩少妇内射免费播放18禁裸乳| 一区二区三区四区五区在线| 国产二区视频在线播放| 日韩激情视频在线观看| 免费看污污网站| 国内精品久久久久影院薰衣草| 日韩欧美理论片| 国产91综合网| 亚洲成人日韩在线| 国产日产欧美一区二区三区| 三级黄色免费观看| 亚洲乱码精品一二三四区日韩在线| 九九免费精品视频| 欧美日韩国产黄| 国模私拍一区二区| 69久久99精品久久久久婷婷| 亚洲精品第五页| 亚洲欧洲日产国产网站| 欧美18hd| 性色av一区二区三区| 日韩大尺度黄色| 国产一区欧美二区三区| 国内精品国产成人国产三级粉色| 欧美精品一区二区三区四区五区| 日韩视频在线观看| 青青青在线视频播放| 天堂在线一区二区| 亚洲一区二区偷拍| 91女人视频在线观看| 91香蕉国产视频| 亚洲.国产.中文慕字在线| 国产乱码77777777| 欧美大胆人体bbbb| www.亚洲资源| 久久久欧美一区二区| 秋霞国产精品| 国产精品v欧美精品v日韩| 精品久久不卡| 国产不卡一区二区视频| 蜜桃一区二区三区在线| 一区二区三区四区影院| 国产精品久久久久久久久免费丝袜 | 久久av网站| 欧日韩一区二区三区| 欧美精品首页| 三上悠亚av一区二区三区| va亚洲va日韩不卡在线观看| 日本免费网站视频| 91极品视觉盛宴| 国产叼嘿视频在线观看| 一本色道久久88精品综合| 毛片大全在线观看| 成人午夜高潮视频| 精品国产一区二区三区小蝌蚪| 免费的一级黄色片| 精品亚洲aⅴ乱码一区二区三区| 国产熟女高潮一区二区三区| 樱桃国产成人精品视频| 中文字幕自拍偷拍| 亚洲人成伊人成综合网久久久| 国产网红在线观看| 成人黄色在线免费| 成人精品视频| 一本久道综合色婷婷五月| 成人毛片在线观看| 欧美片一区二区| 538在线一区二区精品国产| 成年人在线观看网站| 日本最新高清不卡中文字幕| 久久久久影视| 日韩视频免费播放| 国产不卡高清在线观看视频| 欧美精品久久久久久久久46p| 欧美色图免费看| yw在线观看| 国产欧美精品va在线观看| 极品美女一区二区三区| 国产l精品国产亚洲区久久| av电影在线观看完整版一区二区| 国产一级中文字幕| 精品盗摄一区二区三区| 黄色在线看片| 国产伦精品一区二区三区照片91| 国产精品jizz在线观看美国| 亚洲欧洲日韩综合| 一区二区三区精品| 二区三区在线视频| 久久久久久久一区二区三区| 99国产精品免费网站| 日日摸日日碰夜夜爽无码| 99精品桃花视频在线观看| 亚洲国产成人精品激情在线| 亚洲国产日韩欧美在线99| 绿色成人影院| 久久久一本精品99久久精品66| 国产精品一页| 久久久久久国产精品无码| 色8久久人人97超碰香蕉987| 国产福利小视频在线观看| 国产在线视频欧美| 中文乱码免费一区二区三区下载| 无人码人妻一区二区三区免费| 一区二区三区不卡视频在线观看| 亚洲美女性生活| 88国产精品欧美一区二区三区| 伊甸园亚洲一区| 日本黄色的视频| 亚洲自拍偷拍av| 欧美日韩激情视频一区二区三区| 国产精品久久精品| 亚洲电影在线一区二区三区| 麻豆免费在线观看视频| 精品久久久久久久久久| av福利精品| 99超碰麻豆| 每日更新成人在线视频| 后入内射无码人妻一区| 日韩一区二区免费视频| 超碰在线公开| 亚洲国产成人不卡| 粉嫩aⅴ一区二区三区四区| 日韩毛片一区二区三区| 日韩在线免费观看视频| 91精品尤物| av无码精品一区二区三区| 亚洲欧美日韩国产另类专区| 色婷婷av一区二区三区之红樱桃| 国产aⅴ夜夜欢一区二区三区| 午夜精品毛片| av鲁丝一区鲁丝二区鲁丝三区| 欧美色爱综合网| 爱看av在线入口| 在线免费一区| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 日韩欧美二区| 91九色蝌蚪porny| 欧美日韩专区在线| 国产夫妻在线播放| 爱爱爱视频网站| 久久午夜羞羞影院免费观看| 97视频精彩视频在线观看| 国产精品久久久久久久久免费看 | 97在线视频免费观看完整版| 欧美日韩视频在线一区二区观看视频|