美文网首页
三种Block(三)

三种Block(三)

作者: 凉白开0072 | 来源:发表于2017-11-21 11:42 被阅读58次

块的内部结构

<<编写高质量代码的52个有效方法>>中摘抄如下:


图一
图二
图三

OC中的Block的三种类型

OC中,一般Block就分为以下3种:

  1. _NSConcreteStackBlock
    特点:存放在栈区,生命周期由系统控制的,一旦返回之后,就被系统销毁了。
    栈block的表现形式:

    • 条件1:拥有局部变量(自动变量)或者成员属性变量(即使被strong或者copy修饰的成员变量)
    • 没有被强引用
    • 如下面的例1:
  2. _NSConcreteGlobalBlock
    特点:这种Block存储在程序的数据区域(跟函数存储在一起),生命周期从创建到应用程序结束。全局block的copy是个空操作,实际上就相当于单粒.
    全局block的表现形式:

    • block中没有用到任何block内部以外的变量
    • block内部仅仅用到了全局变量/静态全局变量,静态变量
    • 如下面的例2
  3. _NSConcreteMallocBlock:
    特点:存放在堆区,没有强指针引用即销毁,生命周期由程序员控制
    堆block的表现形式:
    堆中的block无法直接创建,其需要由_NSConcreteStackBlock类型的block拷贝而来(也就是说block需要执行copy之后才能存放到堆中)
    在ARC环境下,以下几种情况,编译器会自动的判断,把Block自动的从栈copy到堆

    • 手动调用copy的栈block
    • 栈Block被强引用,被赋值给__strong或者id类型
    • copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock,这可以归纳为上一条
    • Block是函数的返回值
    • 调用系统API入参中含有usingBlcok的方法
    • 举例3:

例1:stackBlock

#import "TestObject.h"

@interface TestObject ()
{
    int b;
}
@property (nonatomic,copy) NSString *str;
@end

@implementation TestObject

- (void)test {
    
    int i = 10;
    //注意,这个block可是srong类型,OC中定义一个变量默认情况下是__strong类型
    //堆block
    //        void (^block)() = ^{i;};
    //栈block
    __weak void (^weakBlock)() = ^{i;};
    // 创建时,都会在栈中
    NSLog(@"%@", ^{i;});
    // 获取了该对象的成员属性变量
    NSLog(@"%@", ^{b;});
    //被copy修饰的str
    NSLog(@"=====%@", ^{ _str;} );
    // 如果是weak类型的block
    NSLog(@"%@", weakBlock);
}
@end

打印结果如下:

<__NSStackBlock__: 0x7fff5b3600f0>
<__NSStackBlock__: 0x7fff5b3600b8>
<__NSStackBlock__: 0x7fff5b360118>
=====<__NSStackBlock__: 0x7fff5594c0a8>

例2:两种globalBlock

#import <Foundation/Foundation.h>

int global_i = 1;
static int static_global_j = 2;

int main(int argc, const char * argv[]) {
    
    static int static_k = 3;
    //globalBlock1:类型1
    void (^myBlock)(void) = ^{
        NSLog(@"Block中 变量 = %d %d %d",static_global_j ,static_k, global_i);
    };
    myBlock();
    NSLog(@"myBlock===%@",myBlock);
    
    //globalBlock2:类型2
    void (^block2)(void) = ^{
    
    };
    NSLog(@"block2===%@",block2);
    return 0;
}

打印结果:

Block中 变量 = 2 3 1
myBlock===<__NSGlobalBlock__: 0x10cc6b050>
block2===<__NSGlobalBlock__: 0x10cc6b090>

例3:堆block


#import "TestObject.h"

@interface TestObject ()
{
    int b;
}
@property (nonatomic,copy) void (^tesblock)();
@property (nonatomic,copy) NSString *str;
@end
@implementation TestObject
- (void)test {
    int i = 10;
    // 1.手动调用copy的栈block
    NSLog(@"%@", [^{i;} copy]);
    //注意,这个block可是srong类型,OC中定义一个变量默认情况下是__strong类型
    //2.栈Block被强引用,被赋值给__strong或者id类型
    void (^block)() = ^{i;};
    NSLog(@"block===%@", block);
    //3.copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock
    self.tesblock = ^{
        //如果没有这个i,那就是全局block,即使用copy引用,也是全局block,从而也说明全局block是不可囊转化成堆block
        i;
    };
     NSLog(@"tesblock===%@", self.tesblock);
    //4.Block是函数的返回值
    NSLog(@"block3===%@", [self test3]);
    //5.调用系统API入参中含有usingBlcok的方法(这个还不懂,以后有空在怼吧)
}
- (void(^)())test3 {
    //如果是全局block那么,即使是函数的返回值,他仍然还是全局block
    //return ^{};
    int a;
    return ^{a;};
}

@end

打印结果:

<__NSMallocBlock__: 0x6000002425b0>
block===<__NSMallocBlock__: 0x60400025c1a0>
tesblock===<__NSMallocBlock__: 0x60400025c290>
block3===<__NSMallocBlock__: 0x60400025c3b0>

block作为函数的参数

当Block为函数参数的时候,需要我们手动copy一份到堆上

- (void)test {
    int i = 10;
    [self test4:^{i;}];
}
- (void)test4:(void (^)())sblock {
    //sblock是一个栈block,需要copy操作
     NSLog(@"sblock===%@", [sblock copy]);
}

相关文章

  • iOS block 为什么官方文档建议用 copy 修饰

    一、block 的三种类型block 三种类型:全局 block,堆 block、栈 block。全局 block...

  • iOS ---block

    block是封装了函数调用和调用环境的oc对象 (一)block的三种形式 block有三种形式,全局block、...

  • Block 与 Closure

    Block In OC block 分为以下三种: _NSConcreteStackBlock:栈block,引用...

  • iOS底层-Block底层原理

    Block函数有三种: 第一种:全局block 第二种:堆区block 第三种:栈区block,栈区block在i...

  • Block

    block- 三种block__NSGlobalBlock__ NSStackBlock __NSMal...

  • OC底层探索26、Block 原理

    一、block简介 1、block的三种类型 NSGlobalBlock - 全局 block NSMallocB...

  • iOS Block

    Block block 类型 block主要有三种类型 NSGlobalBlock:全局block,存储在全局区 ...

  • iOS Block

    Block的分类 Block有三种类型:全局Block,堆区Block,栈区Block 全局Block 当Bloc...

  • block的三种形式

    一、block的三种形式 堆block: 在堆上的block,用__block修饰的外部参数,会将block拷贝(...

  • inline、block、inline-block区别

    display有三种值:inline、block、inline-block display:block将元素显示为...

网友评论

      本文标题:三种Block(三)

      本文链接:https://www.haomeiwen.com/subject/uwgivxtx.html