色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

您好,歡迎來電子發燒友網! ,新用戶?[免費注冊]

您的位置:電子發燒友網>源碼下載>通訊/手機編程>

ObjectiveC中block為什么不能修改變量

大小:0.3 MB 人氣:0 2017-09-25 需要積分:1

2017-08-25 12:04

幾乎每一個iOS開發者都知道,在block中無法修改非靜態局部變量的值,也知道解決方案是用__block來修飾一下變量。

但是,有沒有深入地思考挖掘過呢?比如:

1.為什么block中無法修改非靜態局部變量呢?

第一反應是變量是值傳遞到block中的,故無法修改。為什么對待非靜態局部變量不能像對待靜態局部變量那樣,直接用指針傳遞呢?說到這就不得不說,靜態局部變量和非靜態局部變量的區別了,靜態變量存在于應用程序的整個生命周期,而非靜態局部變量,僅僅是存在于一個局部的上下文中。如果block執行過程中其所指向的非靜態局部變量還沒有被棧回收的話,這樣執行是ok,然后絕大多數情況下,block都是延后執行的,故這樣非常不妥。

在談為什么加__block可以解決此問題之前,我們先討論一個問題,為什么需要我們手動的去添加__block呢,編譯器不能默認都給加上__block呢?如果編譯器這么干了,那么block中所用到的非靜態全局變量在block中都是可以修改的,其實block就是一個匿名函數,而非靜態變量相對于block而言就是外部變量,這就是典型的在函數內修改外部變量,造成了副作用啊。此外,這么干也是有違非靜態變量的初衷,造成了極大的混亂。所以,編譯器默認都加上__block修飾符是不妥的,只能將這個決定權交給開發者自己去決定是加__block還是不加。

2.加__block后是什么鬼?

通過clang 重寫源代碼可以發現用__block修飾后,原來的變量已經被替換成一個與之相對應的struct變量(新變量),比如,定義一個

__block NSMutableArray *array = [NSMutableArray new]; 會變成

__Block_byref_array_1 array = {0,&array, 33554432, size, copyFunc, disposeFunc,[NSMutableArray new] };(經刪除修改)

__Block_byref_array_1的結構體如下所示,

1

2

3

4

5

6

7

8

9  struct __Block_byref_array_1 {

void *__isa;

__Block_byref_array_1 *__forwarding;

int __flags;

int __size;

void (*__Block_byref_id_object_copy)(void*, void*);

void (*__Block_byref_id_object_dispose)(void*);

NSMutableArray *array;

};

通過分析發現,結構體中有一個__forwarding指針,初始化時此指針指向轉換后變量本身;結構體中也有一個原變量一樣類型的變量。

同時,此后代碼中涉及到原變量的地方,都會轉換成新變量-》__forwarding-》原變量同類型變量,其實關于這一點很少有書籍或者文章中提及,如果不能意識到這一點,對于很多問題理解起來會覺得很詫異!

3.__block為什么可行?

通過上面的分析,如果在block中直接修改變量的值,它實質上會轉化成新變量-》__forwarding-》原變量同類型變量。 所以最終修改的其實是結構體中原變量同類型變量,而這個變量明顯已經不屬于block的外部變量了,所以是在block中是可以修改的。

此時,分析到這里,還是有兩個疑問:

·

這個新變量也是非靜態局部變量,block執行的時候,新變量可能已經被棧回收

·

如果block執行時,新變量也已經被釋放的話,程序是會crash的,其實就算用了__block也不能解決這個問題,或者說__block 和這種情況似乎也沒有什么聯系吧!

日常開發中,好像很少遇到這種crash啊?因為實際開發中遇到的block大多數都已經copy到了堆上面,block在copy的時候,也會觸發這個__block變量的copy,會將變量從棧空間copy 到堆空間,所以block在執行的時候,使用的是堆空間上相應的變量,因而不會產生crash!

·

__forwarding的作用是啥?為什么要這么設計?

·

·

__forwarding有什么用? 哪些地方會涉及到呢?

·

從代碼層面上分析,如前文,在使用__block變量時經轉換后,其實都是通過其__forwarding來訪問的

從現象結果來看,如果在block中修改了__block變量,block外修改亦有效,其實這也是__forwarding的功效

·

編譯器是怎么用的?這樣用有什么好處?

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

      ?
      主站蜘蛛池模板: 涩涩爱涩涩片影院 | 国产精品久久久久久人妻精品蜜桃 | 午夜噜噜噜私人影院在线播放 | 97人人爽人人爽人人人片AV | 欧美精品久久久久久久久大尺度 | 亚洲免费高清视频 | 又黄又爽又无遮挡在线观看免费 | 姑娘日本大全免费观看版中文翻译 | 小黄文污到你湿 | 老头扒开粉缝亲我下面 | 一级做a爰片久久毛片一 | 单亲妈妈3韩国电影免费观看 | 日本一区二区三区在线观看网站 | 国产女人91精品嗷嗷嗷嗷 | 亚洲AV福利天堂一区二区三 | 裸妇厨房风流在线观看 | 日韩 国产 中文 无码 | 国产精品九九久久精品视 | www色视频在线观看 WWW色视频片内射 | 快播av种子 | 撅高 自己扒开 调教 | 无码日本亚洲一区久久精品 | 免费99精品国产自在现线 | 日本阿v在线资源无码免费 日本阿v片在线播放免费 | 国产精品第九页 | 亚洲男女羞羞无遮挡久久丫 | 色一欲一性一乱一区二区三区 | 国产成人aaa在线视频免费观看 | 亚洲区视频在线观看 | 亚洲日韩乱码人人爽人人澡人 | 乌克兰美女x?x?y?y | 青青伊人精品 | 国产免费高清mv视频在线观看 | 国产免费麻传媒精品国产AV | 黄子佼81岁父亲现状曝光 | 日本bbwhd | 免费中文字幕视频 | 18禁无遮挡羞羞污污污污免费 | 欧美怡红院视频一区二区三区 | 国产亚洲精品久久精品69 | 久久999视频 |