Block對(duì)象研究

研究工具:clang

創(chuàng)建一個(gè)名為block.c的源文件

#include <stdio.h>

int main(){

^{printf("Hello ,World!\n");}();

return 0;

}

命令行輸入:clang ?-rewrite-objc block.c ? 可在block.c所在的目錄下看到一個(gè)block.cpp文件進(jìn)行分析

block的主要構(gòu)成

isa指針:所有對(duì)象都有該指針,用于實(shí)現(xiàn)對(duì)象的相關(guān)功能

invoke:函數(shù)指針,指向具體的block實(shí)現(xiàn)的函數(shù)指針

descriptor:標(biāo)示該block的附加信息,主要是size大小,以及copy和dispose函數(shù)的指針

variables:block能夠訪問它外部的局部變量,就是因?yàn)檫@些變量(或者變量的地址)復(fù)制到了結(jié)構(gòu)體中

結(jié)構(gòu)體本身并不附帶任何額外信息

創(chuàng)建block時(shí),實(shí)際就是在方法中聲明一個(gè)struct,并且初始化該struct的成員。而執(zhí)行block時(shí),就是調(diào)用那個(gè)單獨(dú)的C函數(shù),并把該struct指針傳遞過去。

在objc中,根據(jù)對(duì)象的定義,凡是首地址是*isa的結(jié)構(gòu)體指針,都可以認(rèn)為是對(duì)象(id).

常見的3種類型的block

_NSConcreteGlobalBlock,全局靜態(tài)block,不會(huì)訪問任何外部變量

_NSConcreteStackBlock,保存在棧中的block,block返回時(shí)被銷毀

_NSConcreteMallocBlock,保存在堆中的block,引用計(jì)數(shù)為0時(shí)被銷毀

只有一個(gè)block被調(diào)用copy方法的時(shí)候,系統(tǒng)才會(huì)將這個(gè)block復(fù)制到堆上,從而產(chǎn)生NSConcreteMallocBlock類型的block

局部變量在block內(nèi)不能被修改

static void__main_block_func_0(struct__main_block_impl_0 *__cself) {

inti = __cself->i;// bound by copy

printf("%d",i);}

在block中引用的局部變量i,實(shí)際上是在聲明block時(shí),被復(fù)制到__main_block_impl_0結(jié)構(gòu)體的那個(gè)變量,block內(nèi)部修改變量i,不會(huì)影響到外部的變量i.

__block修改局部變量

struct__Block_byref_i_0 {

void*__isa;? //凡是首地址是*isa的結(jié)構(gòu)體指針,都可以認(rèn)為是對(duì)象(id).

__Block_byref_i_0 *__forwarding;

int __flags;

int __size;

int i;}

變量i,成了一個(gè)結(jié)構(gòu)體 在__main_block_impl_0 中引用著__Block_byref_i_0 *i;// by ref 結(jié)構(gòu)體指針 ,這樣就起到修改外部局部變量的作用

負(fù)責(zé)結(jié)構(gòu)體__Block_byref_i_0的內(nèi)存管理,增加了copy和dispose函數(shù)指針,用于在調(diào)用前后修改相應(yīng)變量的引用計(jì)數(shù)

static struct__main_block_desc_0 {

size_t reserved;

size_t Block_size;

void(*copy)(struct__main_block_impl_0*,struct__main_block_impl_0*);

void(*dispose)(struct__main_block_impl_0*);

} __main_block_desc_0_DATA = {0,sizeof(struct__main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

ARC對(duì)block類型的影響

int main(int argc,char* argv[]) {

@autoreleasepool{

int i =1024;

void(^block)(void) = ^{

printf("%d",i);

};

block();

NSLog(@"%@",block);

return0;}

}

非ARC運(yùn)行結(jié)果//10242016-06-14 10:46:03.238 MemoryInMRC[7473:3171916] <__NSStackBlock__: 0x7fff5a58f548>

ARC運(yùn)行結(jié)果//10242016-06-14 10:49:03.121 MemoryInMRC[7528:3174176] <__NSMallocBlock__: 0x7fe36a7003e0>

循環(huán)引用

self對(duì)block引用,block捕捉到self時(shí)

XYZBlockKeeper*__weakweakSelf=self; ?self.block=^{ ??[weakSelf doSomething];//捕獲到的是弱引用 ?}

如果捕獲到的是當(dāng)前對(duì)象的成員變量對(duì)象,同樣也會(huì)造成對(duì)self的引用

id ?tmpIvar=_ivar;//臨時(shí)變量,避免了self引用 ??self.block=^{ ??[tmpIvar msg]; ?}

block對(duì)變量的捕獲規(guī)則

靜態(tài)儲(chǔ)存區(qū)變量:全局變量、static修飾變量可以修改

block接受的參數(shù),可以修改

__block引用,可以修改。//bound by reference 如果時(shí)id類型則不會(huì)被block retain,必須手動(dòng)處理其內(nèi)存管理。

局部變量不可以修改//bound by copy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 Blocks是C語言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,869評(píng)論 0 23
  • Blocks Blocks Blocks 是帶有局部變量的匿名函數(shù) 截取自動(dòng)變量值 int main(){ ...
    南京小伙閱讀 1,077評(píng)論 1 3
  • 摘要block是2010年WWDC蘋果為Objective-C提供的一個(gè)新特性,它為我們開發(fā)提供了便利,比如GCD...
    西門吹雪123閱讀 1,001評(píng)論 0 4
  • 1.1 局部變量 局部自動(dòng)變量,在Block中可被讀取。Block定義時(shí)copy變量的值,在Block中作為常量使...
    陳雨塵閱讀 3,041評(píng)論 4 31
  • Block 梳理與疑問 時(shí)隔一年,再次讀 《Objective-C 高級(jí)編程》,看到 block 一章,這一次從頭...
    DeerRun閱讀 750評(píng)論 0 2

友情鏈接更多精彩內(nèi)容