欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶(hù)?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>通訊/手機(jī)編程>

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

大?。?/span>0.3 MB 人氣: 2017-09-25 需要積分:1

2017-08-25 12:04

幾乎每一個(gè)iOS開(kāi)發(fā)者都知道,在block中無(wú)法修改非靜態(tài)局部變量的值,也知道解決方案是用__block來(lái)修飾一下變量。

但是,有沒(méi)有深入地思考挖掘過(guò)呢?比如:

1.為什么block中無(wú)法修改非靜態(tài)局部變量呢?

第一反應(yīng)是變量是值傳遞到block中的,故無(wú)法修改。為什么對(duì)待非靜態(tài)局部變量不能像對(duì)待靜態(tài)局部變量那樣,直接用指針傳遞呢?說(shuō)到這就不得不說(shuō),靜態(tài)局部變量和非靜態(tài)局部變量的區(qū)別了,靜態(tài)變量存在于應(yīng)用程序的整個(gè)生命周期,而非靜態(tài)局部變量,僅僅是存在于一個(gè)局部的上下文中。如果block執(zhí)行過(guò)程中其所指向的非靜態(tài)局部變量還沒(méi)有被?;厥盏脑挘@樣執(zhí)行是ok,然后絕大多數(shù)情況下,block都是延后執(zhí)行的,故這樣非常不妥。

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

2.加__block后是什么鬼?

通過(guò)clang 重寫(xiě)源代碼可以發(fā)現(xiàn)用__block修飾后,原來(lái)的變量已經(jīng)被替換成一個(gè)與之相對(duì)應(yīng)的struct變量(新變量),比如,定義一個(gè)

__block NSMutableArray *array = [NSMutableArray new]; 會(huì)變成

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

__Block_byref_array_1的結(jié)構(gòu)體如下所示,

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;

};

通過(guò)分析發(fā)現(xiàn),結(jié)構(gòu)體中有一個(gè)__forwarding指針,初始化時(shí)此指針指向轉(zhuǎn)換后變量本身;結(jié)構(gòu)體中也有一個(gè)原變量一樣類(lèi)型的變量。

同時(shí),此后代碼中涉及到原變量的地方,都會(huì)轉(zhuǎn)換成新變量-》__forwarding-》原變量同類(lèi)型變量,其實(shí)關(guān)于這一點(diǎn)很少有書(shū)籍或者文章中提及,如果不能意識(shí)到這一點(diǎn),對(duì)于很多問(wèn)題理解起來(lái)會(huì)覺(jué)得很詫異!

3.__block為什么可行?

通過(guò)上面的分析,如果在block中直接修改變量的值,它實(shí)質(zhì)上會(huì)轉(zhuǎn)化成新變量-》__forwarding-》原變量同類(lèi)型變量。 所以最終修改的其實(shí)是結(jié)構(gòu)體中原變量同類(lèi)型變量,而這個(gè)變量明顯已經(jīng)不屬于block的外部變量了,所以是在block中是可以修改的。

此時(shí),分析到這里,還是有兩個(gè)疑問(wèn):

·

這個(gè)新變量也是非靜態(tài)局部變量,block執(zhí)行的時(shí)候,新變量可能已經(jīng)被?;厥?/p>

·

如果block執(zhí)行時(shí),新變量也已經(jīng)被釋放的話,程序是會(huì)crash的,其實(shí)就算用了__block也不能解決這個(gè)問(wèn)題,或者說(shuō)__block 和這種情況似乎也沒(méi)有什么聯(lián)系吧!

日常開(kāi)發(fā)中,好像很少遇到這種crash啊?因?yàn)閷?shí)際開(kāi)發(fā)中遇到的block大多數(shù)都已經(jīng)copy到了堆上面,block在copy的時(shí)候,也會(huì)觸發(fā)這個(gè)__block變量的copy,會(huì)將變量從??臻gcopy 到堆空間,所以block在執(zhí)行的時(shí)候,使用的是堆空間上相應(yīng)的變量,因而不會(huì)產(chǎn)生crash!

·

__forwarding的作用是啥?為什么要這么設(shè)計(jì)?

·

·

__forwarding有什么用? 哪些地方會(huì)涉及到呢?

·

從代碼層面上分析,如前文,在使用__block變量時(shí)經(jīng)轉(zhuǎn)換后,其實(shí)都是通過(guò)其__forwarding來(lái)訪問(wèn)的

從現(xiàn)象結(jié)果來(lái)看,如果在block中修改了__block變量,block外修改亦有效,其實(shí)這也是__forwarding的功效

·

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

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶(hù)評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?