亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

block解析-局部變量

2019-11-14 20:11:52
字體:
來源:轉載
供稿:網友

局部變量

block內使用局部變量,一般都是截獲變量(只讀),截獲離block初始化最近的一次的值。
引用官方文檔:
  1. Stack (non-static) variables local to the enclosing lexical scope are captured as const variables.Their values are taken at the point of the block exPRession within the program. In nested blocks, the value is captured from the nearest enclosing scope. 
 
我們做一個測試,了解一下原理
代碼如下:
-(void )test3{    NSString *_person2=@"person2";    NSMutableArray *_listTest=[[NSMutableArray alloc]init];    //初始值    NSLog(@"init _person2:%@,%p",_person2,_person2);    NSLog(@"init _listTest:%@,%p",_listTest,_listTest);    void (^myBlock)(int) = ^(int num) {        //block內賦值        //        _weakPerson2=@"person22";        NSLog(@"excuteing _person2:%@,%p",_person2,_person2);        NSLog(@"excuteing _listTest:%@,%p",_listTest,_listTest);    };    //修改前賦值    _person2=@"person22";    [_listTest addObject:@"1212"];    NSLog(@"excutebefore _person2:%@,%p",_person2,_person2);    NSLog(@"excutebefore _listTest:%@,%p",_listTest,_listTest);    myBlock(1);    //block執行后    NSLog(@"excuteafter _person2:%@,%p",_person2,_person2);    NSLog(@"excuteafter _listTest:%@,%p",_listTest,_listTest);}

 輸出一下結果:

2014-07-29 11:05:29.460 Test[2540:60b] init _person2:person2,0xb18ec2014-07-29 11:05:29.463 Test[2540:60b] init _listTest:(),0x17d985602014-07-29 11:05:29.464 Test[2540:60b] excutebefore _person2:person22,0xb193c2014-07-29 11:05:29.465 Test[2540:60b] excutebefore _listTest:(    1212),0x17d985602014-07-29 11:05:29.467 Test[2540:60b] excuteing _person2:person2,0xb18ec2014-07-29 11:05:29.468 Test[2540:60b] excuteing _listTest:(    1212),0x17d985602014-07-29 11:05:29.470 Test[2540:60b] excuteafter _person2:person22,0xb193c2014-07-29 11:05:29.471 Test[2540:60b] excuteafter _listTest:(    1212),0x17d98560
 從日志可以看出:block內部對于可變、不可變的變量都無法修改,而且
  1. 在block初始化后對于NSString 變量  _person2 的修改,并沒有同步到block內部,因為這時block外部的變量_person2指針重新指向另外一塊內存
  2. 在block初始化后對于NSMutableArray變量 _listTest 的修改,同步到block內部,因為這時block外部的變量 _listTest 指針指向的內存地址沒有變,只是對這塊內存的值進行了操作。
我們可以借助  clang -rewrite-objc 轉換.c文件得到.cpp文件,也可以轉換.m也可以得到cpp文件(可能會有些報錯)
以下是部分轉換后的代碼
//這里就是block對象的結構
//imp:函數指針對象,FuncPtr指向具體block實現的函數
//_person2:截獲的變量
//isa、flags、funcptr、desc后面會說道。
struct __block_impl {  void *isa;  int Flags;  int Reserved;  void *FuncPtr;};
struct __KDBlockTest__test3_block_impl_0 {  struct __block_impl impl;  struct __KDBlockTest__test3_block_desc_0* Desc;  NSString *_person2;  NSMutableArray *_listTest;  __KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, NSMutableArray *__listTest, int flags=0) : _person2(__person2), _listTest(__listTest) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};

//block實現的函數
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) {  NSString *_person2 = __cself->_person2; // bound by copy  NSMutableArray *_listTest = __cself->_listTest; // bound by copy        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_4,_person2,_person2);        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_5,_listTest,_listTest);    }

 

//block對象的描述信息(大小等等)
static struct __main1_block_desc_0 {  size_t reserved;  size_t Block_size;} __main1_block_desc_0_DATA = { 0, sizeof(struct __main1_block_impl_0)};
//這是objc測試函數test
static void _I_KDBlockTest_test3(KDBlockTest * self, SEL _cmd) {    NSString *_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_1;    NSMutableArray *_listTest=((id (*)(id, SEL))(void *)objc_msgSend)((id)((id (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("alloc")), sel_registerName("init"));    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_2,_person2,_person2);    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_3,_listTest,_listTest);    void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, _listTest, 570425344);    _person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_6;    ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)_listTest, sel_registerName("addObject:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_7);    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_8,_person2,_person2);    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_9,_listTest,_listTest);    ((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1);    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_10,_person2,_person2);    NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_11,_listTest,_listTest);}

 

簡單分析block截獲變量:

 1).block初始化
void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, _listTest, 570425344);

 

傳入了參數:函數指針、block描述、外部變量 _person2 和 _listTest,這時候在block內部對 _person2、_listTest 進行了引用
: _person2(__person2), _listTest(__listTest)

 

  1. 在block初始化后,我們對 _person2 做了修改,重新指向了 0xb193c 這塊內存,但是不會影響block結構體成員_person2,因為成員 _person2 指向的是 0xb18ec。
  2. 向 _listTest 數組中添加了一個元素,并沒有改變它的內存地址,依然還是 0x17d98560 
_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_6;    ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)_listTest, sel_registerName("addObject:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_7);

 

2).執行block
((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);

其實還是調用了block對象里的函數對象(_block_imp1)的函數指針(FuncPtr) 所指向的函數__main1_block_func_0,并把block自己作為參數傳遞進去。

static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) {  NSString *_person2 = __cself->_person2; // bound by copy  NSMutableArray *_listTest = __cself->_listTest; // bound by copy        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_4,_person2,_person2);        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_5,_listTest,_listTest);    }

 

總結:對于局部變量,變量不加__block修飾符,在block內部是無法修改變量的值。而且

  1. 對值類型的修改,如果block初始化后,無法同步到block內部
  2. 對于引用類型的修改,如果block初始化后,修改指針指向,即指向另外一塊內存,這樣也是無法同步到block內部
  3. 對于引用類型的修改,如果block初始化后,對指針指向的內存進行修改,即NSMutableArray add 、remove操作,這樣是可以用同步到block內部,但block內部同樣無法修改。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲毛片在线观看.| 亚洲精品v欧美精品v日韩精品| xx视频.9999.com| 97在线视频免费| 中文字幕日韩在线视频| 国产精品久久av| 92国产精品视频| 777精品视频| 日韩成人在线观看| 国产精品久久久久久久午夜| 欧美精品videosex牲欧美| 久久久久久久久久久久久久久久久久av| 国产激情999| 久久国产精品久久久久久久久久| 亚洲成人av在线播放| 日本成人激情视频| 欧美日韩一区二区三区| 亚洲欧美日韩国产精品| 中文字幕日韩av| 亚洲级视频在线观看免费1级| 国产人妖伪娘一区91| 中文字幕亚洲欧美一区二区三区| 精品中文字幕在线观看| 精品国产户外野外| 91国偷自产一区二区三区的观看方式| 91精品久久久久| 亚洲xxxx视频| 欧美午夜激情视频| 国产成人久久久精品一区| 日韩免费av片在线观看| 亚洲最新av网址| 色综合久综合久久综合久鬼88| 久久精品国产一区二区三区| 成人亚洲激情网| 久久久精品免费| 午夜精品久久久久久久99热浪潮| 久久免费精品日本久久中文字幕| 97精品久久久| 日韩免费在线看| 国产精品网址在线| 国产视频精品自拍| 色噜噜狠狠狠综合曰曰曰88av| 在线成人免费网站| 国产精品免费一区二区三区都可以| 久久不射热爱视频精品| 国产成人aa精品一区在线播放| 亚洲欧美国内爽妇网| 国产精品欧美在线| 欧美激情按摩在线| 欧美日韩在线影院| 日韩美女免费观看| 中文字幕亚洲一区二区三区五十路| 91在线观看免费| 亚洲新声在线观看| 亚洲一区二区久久| 亚洲黄色www| 国产在线播放91| 国产精品国产三级国产aⅴ9色| 国产成人精品在线| 欧美性视频在线| 久久99精品视频一区97| 国产午夜精品免费一区二区三区| 日韩一区在线视频| 在线色欧美三级视频| 久久国产精品久久久久久久久久| 国产精品视频区| 国产一区二区丝袜高跟鞋图片| 欧美激情极品视频| 欧美贵妇videos办公室| 精品久久久久久久久久久久久久| 国产精品欧美一区二区| 91在线视频九色| 亚洲伊人久久大香线蕉av| 中文字幕日韩精品在线| 久久电影一区二区| 国产欧美日韩最新| 欧美日韩在线免费观看| 国产欧美精品一区二区三区-老狼| 欧美视频在线观看免费网址| 亚洲欧美国产精品久久久久久久| 91成品人片a无限观看| 日韩欧美在线视频日韩欧美在线视频| 国产成人精品免费视频| 91网站免费观看| 久久久国产精彩视频美女艺术照福利| 麻豆精品精华液| 欧美高清视频在线观看| 欧美专区中文字幕| 亚洲影院色在线观看免费| 国产女人18毛片水18精品| 日本一区二区在线播放| 亚洲最大的成人网| 136fldh精品导航福利| 青青青国产精品一区二区| 欧美日韩国产中文字幕| 91精品国产自产在线| 欧美激情精品久久久久久蜜臀| 中文字幕日本欧美| 欧美精品在线免费| 国产亚洲精品久久久久久| 欧美性jizz18性欧美| 91九色国产在线| 亚洲最大福利网| 欧美与欧洲交xxxx免费观看| 国产成人精品免高潮在线观看| 亚洲成人久久久| 丝袜亚洲另类欧美重口| 日韩在线中文视频| 欧美日韩精品在线视频| 最近2019免费中文字幕视频三| 欧美精品久久久久久久免费观看| 欧美日韩亚洲精品一区二区三区| 国产成人高清激情视频在线观看| 久久亚洲欧美日韩精品专区| 九九精品在线播放| 欧美黄色免费网站| 久久久久成人精品| 国产+成+人+亚洲欧洲| 欧美性猛交xxxxx免费看| 亚洲精品一区久久久久久| 国产精品27p| 精品视频久久久久久| 欧美在线欧美在线| 精品国内产的精品视频在线观看| 国产精品无av码在线观看| 国产成人欧美在线观看| 国产精品一区二区久久| 岛国精品视频在线播放| 影音先锋欧美精品| 欧美激情一区二区三级高清视频| 亚洲视频在线观看| 日韩在线观看免费全| 日韩精品视频在线| 成人有码在线视频| 青青a在线精品免费观看| 国产精品视频在线播放| 欧美剧在线观看| 亚洲欧美日本伦理| 91伊人影院在线播放| 欧美国产一区二区三区| 97超碰蝌蚪网人人做人人爽| 久久久久久久网站| 亚洲精品999| 蜜臀久久99精品久久久无需会员| 欧美性猛交xxxxx免费看| 欧美性猛交xxxx富婆| 国产精品久久久久久久久粉嫩av| 日韩欧美在线视频| 91精品久久久久久久久久另类| 97免费视频在线| 亚洲网站视频福利| 2020久久国产精品| 日本亚洲欧美三级| 欧美精品久久久久久久| 国产精品免费一区豆花| 亚洲精品资源美女情侣酒店| 欧美大片欧美激情性色a∨久久| 亚洲人成伊人成综合网久久久| 亚洲男子天堂网| 91精品国产91久久久久福利| 性欧美xxxx交| 欧美老女人性视频| 一区二区三区在线播放欧美| 国产区亚洲区欧美区|