block系列1-block使用

1.使用Blocks


(1)block概念

Blocks是带有自动变了(局部变量)的匿名函数。其写法遵循BN范式

^ 返回值类型 参数列表 表达式

返回值类型可省略,参数列表亦可省略。可以定一个Blocks变量来获得匿名函数的使用权

int (^blk)(int) = ^(int count){return count+1};

我们可以作为参数传递Blocks变量,也可以返回Blocks类型变量,也可以使用typedef定义更方便使用Blocks变量

void func(int (^blk)(int)){}

int (^func())(int){
    return ^(int count){return count+1};
}

typedef int (^blc_t)(int);
  • block的代码是内联的,效率高于函数调用
  • block对于外部变量默认是只读属性,要在block内修改外部变量需要添加_block关键字修饰
  • block被Objective-C看成是对象处理

block会捕获在其定义时的变量值,变量修改后并不会影响block中使用的变量。

{
    int a = 10;
    int (^blc)(int) = int ^(int count){return count+a;};
    a++;
    NSLog(@"%@",blc(5));//打印15,而不是16
}

变量的复制关系如下

block外变量引用,默认是复制到block内的readonly变量

[站外图片上传中...(image-7c89d1-1524555790555)]

对于用__ block修饰的外部变量引用,block复制其引用地址来实现访问

[站外图片上传中...(image-a85bf0-1524555790555)]

(2)block常见用法:

  1. 局部位置声明一个Block型的变量

    return_type (^blockName)(var_type) = ^return_type (var_type varName) {
        // ...
    };
    blockName(var);
    
  2. @interface声明Block型属性

    @property(nonatomic, copy)return_type (^blockName) (var_type);
    
  3. Block型作为形参

    - (void)yourMethod:(return_type (^)(var_type))blockName;
    
  4. 内联用法,定义后立即调用,不常用

    ^return_type (var_type varName)
    {
        //...
    }(var);
    
  5. 递归调用

    使用__block避免循环引用问题。

    __block return_type (^blockName)(var_type) = [^return_type (var_type varName)
    {
        if (returnCondition)
        {
            blockName = nil;
            return;
        }
        // ...
        // 【递归调用】
        blockName(varName);
    } copy];
    
    【初次调用】
    blockName(varValue);
    
  6. 作为返回值

    - (return_type(^)(var_type))methodName
    {
        return ^return_type(var_type param) {
            // ...
        };
    }
    

2.block原理


(1)数据结构定义

block的数据结构定义如下

[站外图片上传中...(image-894ad2-1524555790555)]

结构体定义如下

#define BLOCK_DESCRIPTOR_1 1
struct Block_descriptor_1 {
    unsigned long int reserved;
    unsigned long int size;
};
struct Block_layout {
    void *isa;
    volatile int flags; // contains ref count
    int reserved; 
    void (*invoke)(void *, ...);
    struct Block_descriptor_1 *descriptor;
    // imported variables
};
//Block-private.h

对于每个参数解释如下

  1. isa: 对象指针
  2. flags: 记录block的一些附加信息,包括引用计数
  3. reserved: 保留变量。
  4. invoke: 函数指针,指向block函数实现地址。
  5. descriptor:附加信息描述
//falgs bit位描述如下
enum {
    BLOCK_DEALLOCATING =      (0x0001),  // runtime
    BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
    BLOCK_NEEDS_FREE =        (1 << 24), // runtime
    BLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
    BLOCK_HAS_CTOR =          (1 << 26), // compiler: helpers have C++ code
    BLOCK_IS_GC =             (1 << 27), // runtime
    BLOCK_IS_GLOBAL =         (1 << 28), // compiler
    BLOCK_USE_STRET =         (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
    BLOCK_HAS_SIGNATURE  =    (1 << 30)  // compiler
};

从枚举变量的定义可以看出flags的bit位作用,第0位表示释放内存标志,1-23bit作为引用计数值,24-31略过。

在OC中有三种block

  1. _NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量。
  2. _NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁,ARC下不适用。
  3. _NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁。

下篇文章讲解不同block的实现方式

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容