__block變量的成員變量__forwarding存在的意義
</br>
__block變量結(jié)構(gòu)體中的__forwarding成員變量是個指向自身的指針,為什么需要這樣一個“多此一舉”的變量呢沽翔?
Block從棧復(fù)制到堆上時兢孝,__forwarding發(fā)生的變化:
Block復(fù)制后,棧上__block變量的__forwarding指針被修改仅偎,指向了堆上的__block變量跨蟹。
通過__forwarding指針,我們可以實現(xiàn)橘沥,無論是在Block語法中窗轩、Block語法外,還是__block變量配置在棧上或堆上座咆,都可以順利訪問同一個__block變量
下面是分別在Block語法中和Block語法外訪問__block變量的例子?痢艺,這能反映__forwarding成員變量存在的意義:
__block int val = 0;
void (^blk)(void) = [^{++val; } copy]; //語句1
++val; //語句2
blk(); //語句3
NSLog("%d", val);
代碼分析:
語句1
的copy方法把Block從棧復(fù)制到堆〔滞荩現(xiàn)在棧和堆上都有這個Block。語句2
和語句3
都是訪問__block變量堤舒,但它們有所區(qū)別:語句2
?在Block語法外訪問__block變量色建,并且訪問的是棧上的__block變量;語句3
?在Block語法中訪問__block變量舌缤,并且也是訪問棧上的__block變量箕戳。所以語句2
和語句3
都等價于
++(val.__forwarding->val);
雖然它們訪問的都是棧上的__block變量,但因為Block執(zhí)行復(fù)制之后友驮,__forwarding會修改為指向堆上的__block變量漂羊,所以本質(zhì)上訪問的是堆上的__block變量。
?假如沒有__forwarding成員變量卸留,我們執(zhí)行上例的代碼時,++val;
和blk();
兩條語句訪問的都是棧上__block變量椭豫。這樣你看出問題了嗎耻瑟?棧上和堆上的__block變量的值不一致了:一旦棧上的__block變量隨著Block變量作用域結(jié)束被廢棄而被廢棄,稍后訪問堆上的__block變量時赏酥,訪問到的是個錯誤(不是預(yù)期想要的)的值喳整。