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

深究Block的實現

移動開發
從編譯過后的代碼中,去理解ios中的block是怎么實現的

[[163549]]

先看一下Block使用的語法

聲明一個block
返回值 (^名稱)(參數列表) = ^(參數列表){
};

  1. int (^name)(int ,int) = ^(int a,int b){ 
  2.       
  3.      return (a+b); 
  4. }; 

作為一個函數的參數:

  1. - (void)testBlock:(NSString *(返回類型) (^)(int a))s(block名字) { 
  2. NSString *a = s(1); 
  3.    
  4.  [self testBlock:^NSString *(int a) { 
  5.       
  6.      a = 5
  7.       
  8.      return @"1"
  9. }]; 

然后通過底層代碼分析一下block的實現

iOS中有三種block,下文會細說
NSConcreteGlobalBlock;//在全局中定義的
NSConcreteStackBlock; //在局部定義的
NSConcreteMallocBlock;//分配在堆中

先從最簡單的看起

  1. int main(int argc, char * argv[]) { 
  2. void (^block)(void) = ^{     
  3.   NSLog(@"1"); 
  4. }; 

(通過 在終端找到這個.m文件,然后clang -rewrite-objc 代碼文件名 就可以看到文件夾有個.cpp的文件,本來想變量ViewController的文件,里面用了UIKit庫,編譯的時候總是顯示找不到,于是我編譯的main.m文件)

編譯過來是

block源碼

這里先來分析一下(便于理解):

  1. static void _main_block_func_0(struct _main_block_impl_0 *__cself) { 
  2.  NSLog((NSString *)&__NSConstantStringImpl__var_ 
  3. folders_yq_s_hjnhd12x79wq1ldg1jdr_w0000gn_T_main_50d1d6_mi_0); 

可以看到,這里對應我們代碼中的block中的實現,所以可以知道,block使用的匿名函數,實際上被當作一個函數來處理。不過傳入的是:一個_main_block_impl_0類型的結構體,里面有一個block_impl的結構體,和一個_main_block_desc_0的結構體。跟著是他們的構造函數。
來簡單看一下這個_main_block_impl_0結構體吧:

isa指向這個block的類型。這里說明這個block是NSConcreteStackBlock類型的。
flag是標志,可以看到,默認構造為0;
還有一個FuncPtr,也就是指向函數地址的指針。
還有一個__main_block_desc_0的結構體,
在下面可以看到這個結構體的初始化,
一個是reserverd默認為0,
一個是block_size。是這個impl的size。
所以,這個_main_block_impl_0,我們可以理解為就是一個block實例,里面的成員變量有要執行的函數的指針,和isa(和所有的oc對象一樣),還有一個size。

現在看一下main函數里面的內容

  1. void (*name)(void) = ((void (*)())&__main_block_impl_0((void  
  2. *)__main_block_func_0, &__main_block_desc_0_DATA)); 

這里執行的操作就是:初始化一個block實例,交給我們這么name名字變量,也就是用name這個指針指向這個block實例,執行的時候,直接找到這個block中的指向函數地址的指針。

通過以上可以了解:block的實質,就是一個對象,包含了一個指向函數首地址的指針,和一些與自己相關的成員變量。

接著看一下block訪問外部變量是怎么回事,這也是我們最關心的問題。

先來看一下局部變量:

  1. int a = 10
  2. int b = 20
  3. void (^block)() = ^ { 
  4.    NSLog(@"%d--%d",a,b); 
  5. }; 
  6. block (); 

block訪問局部變量

首先在_main_block_impl_0的定義中看到,block中用到的變量被作為成員變量追加到了結構體中,

  1. _main_block_impl_0(void *fp, struct _main_block_desc_0 *desc,  
  2. int _a, int _b, int flags=0) : a(_a), b(_b) { 
  3. impl.isa = &_NSConcreteStackBlock; 
  4. impl.Flags = flags; 
  5. impl.FuncPtr = fp; 
  6. Desc = desc; 

在初始化的時候,也需要把a和b的值傳入。

  1. void (**block)() = ((void (*)())&_main_block_impl_0((void *) 
  2. _main_block_func_0, &_main_block_desc_0_DATA, a, b)); 

這里看到,在初始化的時候,把a,b值傳入來初始化一個_main_block_impl_0結構體。這里需要注意,傳入的是a和b的值,所以我們要在結構體中改變a和b是無效的。并且編譯會報錯,如果要在block中改變里面的值。有以下幾種方法

1,靜態變量,全局變量

直接上代碼吧,嘻嘻

  1. int global_val  = 1
  2. static int static_global_val = 2
  3. int main(int argc, char * argv[]) { 
  4. static int static_val = 3
  5. void (^block)() = ^ { 
  6.     global_val = 10
  7.     static_global_val = 20
  8.     static_val = 30
  9. }; 
  10. NSLog(@"%d-%d-%d",global_val,static_global_val,static_val); 
  11. block (); 
  12. NSLog(@"%d-%d-%d",global_val,static_global_val,static_val); 

然后rewrite一下

訪問全局變量

因為這個_main_block_func_0能直接訪問靜態變量,所以可以直接訪問這個變量的值,也可以改變,不用擔心在調用這個函數的時候,全局變量訪問不到,導致錯誤。所以這里面在調用全局變量的時候,就是很普通的調用全局變量,沒有什么不同。

局部靜態變量則傳的是一個指針進來。因為不用擔心它在函數結束時或者其他什么地方被釋放,所以可以放心的訪問這個值。

  1. global_val = 10
  2.    static_global_val = 20
  3.    (*static_val) = 30

改變的是這個指針指向的值

  1. void (*block)() = ((void (*)())&__main_block_impl_0((void *) 
  2. _main_block_func_0, &__main_block_desc_0_DATA, &static_val)); 

可以看到,這里傳的是指針。
_main_block_func_0的作用域在main函數之外,要訪問這個變量,就只能傳指針。

第二種方法是給參數加__block屬性

  1. int main(int argc, char * argv[]) { 
  2. __block int block_val = 3
  3. void (^block)() = ^ {         
  4.  block_val = 30
  5. }; 
  6. NSLog(@"%d",block_val); 
  7. block (); 
  8. NSLog(@"%d",block_val); 
  9. NSLog(@"%@",block); 

__block參數

可以看到里面比其他多了一個這樣的結構體_Block_byref_block_val_0
里面有:

_isa初始化為0,
__forwarding;//持有該實例自身的的指針
int flags;為0
int s__Block_byref_block_val_0ize;size
int block_val;//存放這個變量的值
原來是把一個局部變量,封裝成了一個結構體
賦值的時候直接給這個結構體中的這個值賦值
(block_val->__forwarding->block_val) = 30;

所以,在訪問這個變量的時候,其實在訪問這個結構體的這個變量。

關于_forwarding的作用請不要著急。

Block有三種類型:

  1. { 
  2. NSConcreteGlobalBlock;//在全局中定義的 
  3. NSConcreteStackBlock; //在局部定義的 
  4. NSConcreteMallocBlock;//分配在堆中 
  5. } 

設置在棧上的block,當“name這個名字變量”作用域結束時,block變量也會廢棄。
所以,iOS提供了將block結構體和_block變量,復制到堆上的方法。即使block的name變量結束,那么堆上的block還可以繼續訪問。
而此時,_block變量結構體中的_forwarding變量可以實現,無論在堆上還是在棧上。都可以正確訪問_block變量。可以理解,當把_block變量復制到堆上的時候,_forwarding就指向堆里中的自己。所以無論是訪問棧中自己,還是堆中的自己,最終訪問都是堆中的這個值。

一個Block對_block的內存管理方式與 ARC機制完全相同。
而_main_block_desc 中的copy和dispose就是這個 __block的retain和release操作。

那什么block在時候會復制到堆呢?

  1. 掉用block的copy方法。
  2. block作為函數返回值返回時。
  3. block調用外面的_strong的id的類時,或用_block時。
  4. 方法中,用usingblock或者GCD中的API時。

這里想講一下,在局部函數里,定義block時,打印出來還是NSConcreteGlobalBlock類型的,而且只要用了外部變量,不管是assign還是week還是strong類型的,打印出來都是NSConcreteMallocBlock類型的。所以我猜測這會不會是蘋果新版的改進,為了block在訪問無效的變量,直接把block拷貝到堆上,從而也拷貝一份變量。或許是我忽略了中間的某個步驟

其實到了這里,不用再描述,也知道為什么會發送死循環,又怎么解決了。當在block中用self的時候,block拷貝到堆上,首先,在棧上的這個block有一個持有者,是name這個變量。當name這個變量作用域之外,棧上這個block就release了。,那么當block拷貝到堆上的時候,block有一個持有者是self,那么block在拷貝時,它的變量一個self指針,也會拷貝,而self又指向這個block,block持有self,self持有block,兩者都不會釋放。要打破這個循環,需要將self置為__week,就算拷貝一個week指針,那也不影響self的引用計數。

責任編輯:倪明 來源: CocoaChina
相關推薦

2010-12-20 15:25:36

編譯時間.NET

2022-11-11 10:56:37

2013-04-08 10:08:22

開源虛擬化KVM

2013-05-29 15:33:01

開源虛擬化KVM

2013-04-07 09:33:31

開源虛擬化KVM

2020-11-10 15:25:26

SemaphoreLinux翻譯

2021-12-31 07:48:58

Vue3 插件Vue應用

2013-06-04 15:41:31

iOS開發移動開發block

2021-12-18 20:46:38

亞馬遜云科技阿里云IaaS

2018-01-04 10:08:08

2010-09-16 09:13:09

CSS display

2017-03-07 09:45:43

iOSBlock開發

2014-07-30 11:12:09

block

2010-04-07 16:54:55

Oracle性能

2010-09-03 12:55:15

CSSblockinline

2014-07-31 16:47:10

block

2025-01-10 09:47:43

blockSDKiOS

2010-01-06 16:22:53

第三層交換技術

2017-05-12 17:58:11

2013-07-19 12:52:50

iOS中BlockiOS開發學習
點贊
收藏

51CTO技術棧公眾號

a级黄色片免费看| 成人免费播放器| 国产又大又黑又粗| 亚洲国内自拍| 在线成人免费网站| 黄色片子免费看| 免费成人直播| 亚洲精品免费在线| 一区二区自拍| 日韩欧美在线网站| 亚洲av综合色区| 欧美孕妇孕交xxⅹ孕妇交| 天堂一区二区在线| 欧美激情啊啊啊| www.99热| 看全色黄大色大片免费久久久| 91碰在线视频| 成人有码在线播放| 福利网址在线观看| 欧美视频四区| 夜夜嗨av色综合久久久综合网| 亚洲精品久久久久久久蜜桃臀| 国产女人高潮毛片| 国产日韩欧美| 欧美成人剧情片在线观看| 国产吞精囗交久久久| 精品国产亚洲日本| 欧美性感一区二区三区| 欧美一区二区三区爽大粗免费| 日韩一区二区三区在线观看视频 | 制服丝袜激情欧洲亚洲| 亚洲熟妇av一区二区三区漫画| 黑人精品一区二区三区| 日本v片在线高清不卡在线观看| 国产午夜精品免费一区二区三区| 成人黄色一区二区| 精品久久久久久久无码| 精品人妻少妇AV无码专区| 国产美女精品| 久久久久久久国产| 一级黄色录像视频| 国产高清欧美| 中文字幕日韩专区| 四虎国产精品成人免费入口| 精品亚洲免a| 欧美成人三级电影在线| 国产毛片久久久久久| 成人免费黄色| 日本韩国欧美在线| wwwxxx黄色片| 欧美成人影院| 日韩欧美中文字幕在线观看 | 亚洲美女性囗交| 91最新在线视频| 国产精品青草久久| 日本一区二区高清视频| 五月激情丁香婷婷| www.久久久久久久久| 高清一区二区三区视频| 不卡视频免费在线观看| 亚洲av无码国产精品永久一区| 国产剧情一区二区在线观看| 欧美日韩在线三级| 国产色视频在线播放| 国产亚洲一区二区手机在线观看| 综合久久久久综合| 国产欧美综合一区| 色呦呦在线看| 亚洲自拍偷拍网站| 国产九色porny| 啊啊啊久久久| 色综合天天视频在线观看| 97成人在线观看视频| 成人看片网页| 欧美老人xxxx18| 永久免费黄色片| 日韩影片在线观看| 亚洲精品一区二区三区99| 一级国产黄色片| 伊人久久大香线蕉无限次| 国产亚洲精品久久久| 美国一级黄色录像| 欧美91视频| 久久人人爽人人| 国产欧美一区二区三区在线看蜜臂| 欧美激情第10页| 久久久人成影片一区二区三区| 久久久久麻豆v国产| 91精品国产视频| 欧美激情第99页| 中文字幕黄色片| 韩国精品久久久| 国产精品久久久久久久久久久久冷| 91麻豆国产在线| 国产精品88888| 久久久久久国产精品mv| 免费人成在线观看播放视频| 一区二区三区在线观看欧美 | 午夜精品毛片| 日韩精品免费视频人成| 亚洲成人999| 国产jjizz一区二区三区视频| 国产电影一区| 日韩黄色在线免费观看| 国产又粗又长又硬| 亚洲看片免费| 91精品免费视频| 日色在线视频| 一区2区3区在线看| 久久久精品麻豆| 日本成人手机在线| 亚洲一区二区国产| 青青草激情视频| 日本免费新一区视频| 国产成人精品福利一区二区三区| 性生交大片免费看女人按摩| 久久久久99精品国产片| 8x8x华人在线| 韩国精品主播一区二区在线观看 | 91丨九色丨黑人外教| 亚洲精品一区二区三| 亚洲天堂av影院| 日韩女优制服丝袜电影| 992在线观看| 香蕉久久夜色精品| 国产高清不卡av| 国产成人l区| 欧美日韩在线直播| 中文字幕免费视频| 在线一区欧美| 98国产高清一区| 大片免费在线看视频| 欧美网站大全在线观看| 30一40一50老女人毛片| 激情欧美亚洲| av一区二区三区四区电影| 日本在线免费播放| 欧美在线观看一区二区| 亚洲人成人无码网www国产| 伊人成人网在线看| 国产成人女人毛片视频在线| 亚洲v在线观看| 中文字幕日本在线观看| 好吊成人免视频| 香港三级日本三级| 99av国产精品欲麻豆| 成人自拍视频网站| 在线视频观看国产| 91精品国产高清一区二区三区| 男人的天堂免费| 欧美91福利在线观看| 91久久国产综合久久蜜月精品| 天堂在线视频网站| 香蕉乱码成人久久天堂爱免费| 日韩免费高清在线| 欧美日韩精品一区二区视频| 国产精品成人免费电影| 国产大学生校花援交在线播放 | 精品久久久三级丝袜| 911国产在线| 久久精品国产精品青草| 亚洲永久激情精品| 成人在线视频www| 精品自在线视频| 亚洲第九十九页| 亚洲成人av在线电影| av无码一区二区三区| 性一交一乱一区二区洋洋av| 免费成人深夜夜行视频| 日韩av中字| 最近2019年手机中文字幕| 一级黄色片在线观看| 亚洲精品中文字幕乱码三区| 女人扒开双腿让男人捅| 在线日本成人| 欧美在线视频二区| 伊人亚洲精品| 欧美激情在线播放| 男女污污视频在线观看| 欧美色手机在线观看| 日韩va亚洲va欧美va清高| 国产.欧美.日韩| 欧美精品99久久| 欧美日韩精品一区二区视频| 91在线视频九色| 国产夫妻在线| 色多多国产成人永久免费网站 | 丝袜诱惑亚洲看片| 亚洲激情一区二区三区| 日本黄色一区二区三区| 试看120秒一区二区三区| 日韩在线中文字幕| 亚洲经典一区二区| 日本道精品一区二区三区| 国产人与禽zoz0性伦| 成人免费观看男女羞羞视频| 污污视频网站免费观看| 欧美在线免费| 九色综合婷婷综合| 91视频亚洲| 欧美一级bbbbb性bbbb喷潮片| 精品久久久中文字幕人妻| 五月婷婷激情综合| 青青操在线播放| 91麻豆精品秘密| 中文字幕一区二区三区四| 水野朝阳av一区二区三区| 亚洲高潮无码久久| 欧美日韩高清| 国产视频在线观看一区| 欧美亚洲黄色| 国产成人鲁鲁免费视频a| av在线免费网站| 亚洲视频第一页| 欧美视频一二区| 制服丝袜国产精品| 中国a一片一级一片| 亚洲第一成人在线| 中文字幕亚洲欧美日韩| 久久久久88色偷偷免费| 99久久免费看精品国产一区| 国内精品视频一区二区三区八戒| 国内精品国产三级国产99| 国产精品免费不| 狠狠色噜噜狠狠狠狠色吗综合| 成入视频在线观看| 久久亚洲精品成人| 最新av网站在线观看| 精品视频久久久久久久| 亚洲国产精彩视频| 69p69国产精品| 最好看的日本字幕mv视频大全| 国产精品欧美一区喷水| 深爱五月激情网| 99久久精品情趣| 蜜臀aⅴ国产精品久久久国产老师| 激情欧美一区| 欧美 亚洲 视频| 婷婷亚洲最大| 亚洲图片都市激情| 全球成人免费直播| 视频一区国产精品| 欧美理论在线播放| 日本不卡一区| 国产精品一区2区3区| 欧美另类一区| 国产成人一区| 日韩av一级大片| 国产精品乱子伦| 亚洲欧洲日韩在线| 欧美88888| 自拍偷拍亚洲综合| 久久精品一区二区三区四区五区| 国产精品77777| gogo亚洲国模私拍人体| 国产美女av一区二区三区| 性鲍视频在线观看| 国产电影精品久久禁18| 男插女视频网站| 成人网页在线观看| av网页在线观看| 久久综合色天天久久综合图片| 日本高清免费在线视频| 国产精品18久久久久| av地址在线观看| 不卡av免费在线观看| 亚洲调教欧美在线| 久久久不卡网国产精品二区| 亚欧精品视频一区二区三区| 亚洲私人影院在线观看| 中文字幕在线观看成人| 红桃av永久久久| 樱花视频在线免费观看| 欧美久久久一区| 黑人乱码一区二区三区av| 亚洲女人天堂成人av在线| 伦理片一区二区三区| 久久精品欧美视频| 成人影音在线| 国产91色在线|免| 亚洲日本中文| 国产精品日韩欧美一区二区三区| 四虎国产精品免费久久5151| 亚洲综合在线小说| 高清精品视频| 日韩影片在线播放| 午夜天堂精品久久久久| 日本少妇高潮喷水视频| 日本最新不卡在线| 久久aaaa片一区二区| 91免费精品国自产拍在线不卡 | 成人午夜视频网站| 久久中文字幕人妻| 亚洲欧美偷拍另类a∨色屁股| 国产又粗又猛又爽又黄的视频四季| 99久久国产综合精品女不卡| 免费一级做a爰片久久毛片潮| 91理论电影在线观看| 麻豆一区在线观看| 精品露脸国产偷人在视频| 国产又粗又大又黄| 亚洲欧美一区二区三区在线| 成码无人av片在线观看网站| 欧洲成人在线视频| 麻豆视频久久| 美乳视频一区二区| 欧美日韩亚洲一区| 亚洲精品久久久中文字幕| 成人成人成人在线视频| 人人澡人人澡人人看| 富二代精品短视频| 精品乱子伦一区二区三区| 久草成人资源| 欧美成人精品免费| 精品在线免费观看| 久久亚洲AV无码专区成人国产| 97se亚洲国产综合自在线不卡| 国产又黄又粗又猛又爽的视频 | 国产黄色网址在线观看| 国产精品国产a级| 天堂网中文字幕| 欧美精品一区二区三区很污很色的 | 国产ts丝袜人妖系列视频| 亚洲色大成网站www久久九九| 国产成人综合在线视频| 在线观看日韩电影| 日韩porn| 性欧美长视频免费观看不卡| 国产精品久久久久久av公交车| av一本久道久久波多野结衣| 999精品在线| 狠狠热免费视频| 99精品国产91久久久久久 | 18涩涩午夜精品.www| 亚洲欧美一区二区三区在线观看| 91搞黄在线观看| 三级在线观看| 欧美一区视频在线| 国产毛片久久久| 青青在线视频免费观看| 国产在线视频不卡二| 麻豆网址在线观看| 在线成人免费观看| 三级外国片在线观看视频| 国产精品永久免费| 四虎成人精品永久免费av九九| a天堂资源在线观看| 国产高清在线精品| 欧美日韩一级大片| 欧美成人性战久久| gogo高清在线播放免费| 国产亚洲自拍偷拍| 一区二区三区精品视频在线观看| 色www免费视频| 国产精品剧情在线亚洲| 一级片视频免费| 欧美成人一二三| 97品白浆高清久久久久久| 久草视频国产在线| 91美女精品福利| 丰满少妇xoxoxo视频| 一区二区三区在线播放欧美| 久久精品超碰| 中文字幕剧情在线观看一区| 国产一区二区三区蝌蚪| 黄色一级片在线| 亚洲精美色品网站| 成人影院网站| 亚洲精品乱码视频| 国产一区二区三区免费看| 一级aaa毛片| 亚洲美女av在线播放| 国产精品99久久久久久董美香 | 成人在线丰满少妇av| 国产噜噜噜噜噜久久久久久久久| 在线播放国产一区| 中文字幕亚洲欧美日韩高清 | 妖精视频一区二区三区| 成人一区二区三| 国产精品青草久久| 精品免费久久久| 性亚洲最疯狂xxxx高清| 亚洲区小说区图片区qvod| 一道本在线免费视频| 夜夜嗨av一区二区三区网页| 色婷婷av一区二区三区之e本道| 久久99精品视频一区97| 大香伊人久久精品一区二区| 国产1区2区在线| 亚洲卡通欧美制服中文| 欧洲一级在线观看| 91九色蝌蚪嫩草| 久久福利影视| 日本黄色小说视频| 亚洲日韩中文字幕| 日韩免费成人| 中文字幕第36页| 午夜精品爽啪视频| 男人的天堂在线视频免费观看| 国产精品私拍pans大尺度在线|