zoukankan      html  css  js  c++  java
  • OC 的 Block 简析1

    本文主要介绍 Block 的三种类型。

    OC底层探索26、Block 原理

    一、Block 是什么?

    在 OC 文档的 Working with Blocks 中:

      Blocks are Objective-C objects, which means they can be added to collections like NSArray or NSDictionary.

    Block 官方文档: Block Programming Topics 中:

      As an optimization, block storage starts out on the stack—just like blocks themselves do.

    block 是一个 OC 对象,但是它和普通的O从对象又不一样。

    block 默认在 栈上分内存,而我们一般的对象是在堆上。

    二、block 有三种类型: 全局 / 栈 / 堆  block

    1、全局block -  __NSGlobalBlock__

    - (void)block3 {
        // 声明: typedef  NSString *(^MyBlock)(NSString *str);
        MyBlock block = ^(NSString *str){
            
            NSLog(@"处理一些无关于外部属性的事务");
            return str;
        };
        block(@"");
        NSLog(@"block类型%@",block);
    }

    2、栈block -  __NSStackBlock__

    - (void)block2 {
        
        int a = 1;
        
        NSLog(@"block类型%@",^{ NSLog(@"block 0:%i", a); });
    }

    3、堆block -  __NSMallocBlock__

    - (void)block1 {
        void (^blockObject)(void);
        blockObject = ^{ NSLog(@"block 0:%i", a); };
        blockObject();
        
        NSLog(@"block类型%@",blockObject);
    }

    从上面3部分代码中,我们可看出三者区别:

    全局block:block 没有访问任何外部变量的;

    栈block: block 访问了外部对象,但没有copy操作;

    堆block:相对于栈block来说:我们声明定义了一个block同时访问了外部变量则(不访问就是全局)(不声明定义就是栈),此过程本质就是栈-变->堆的过程,系统帮我们做了copy,栈的block迁移到了堆里。

    4、关于堆block 详解

    代码示例:

    - (void)block1 {
        
        /* __block 允许block内部使用,
        */
        __block NSString *blockStr = @"局部str";
        MyBlock block = ^(NSString *str){
            
            /*
             block 内部操作:将对象 copy 了一个新的到堆上,指针不变,但指针指向新的对象
            */
            self->globalStr = @"block内修改全局";
             blockStr = str;
    
            NSLog(@"内globalStr== %@ %p %p",self->globalStr,self->globalStr,&self->globalStr);
    
            [self logstr:blockStr];
            
            return str;
        };
        
        NSLog(@"block类型%@",block);
        NSLog(@"外globalStr== %@ %p %p",globalStr,globalStr,&globalStr);
        NSLog(@"外blockStr== %@ %p %p",blockStr,blockStr,&blockStr);
    
        block(@"执行block,改局部str");
    }
    - (void)logstr:(NSString *)blockStr {
        
        NSLog(@"globalStr2== %@ %p %p",globalStr,globalStr,&globalStr);
    
        /*
         局部str,拿到外部,创建了一个新的指向它的指针
        */
        NSLog(@"blockStr2== %@ %p %p",blockStr,blockStr,&blockStr);
    }

    运行结果如图:

     

    我们可以看到,不论是函数中的局部变量 还是当前文件范围的局部变量(注意:代码里的‘全局’并非是真正的全局,只是为了用来区分函数内部变量), 在 block 内部进行使用,对象都不是外部的那个对象了,但是指向对象的指针不变 --> 即:指针指向的对象是一个copy出来的新的。如下图:

     

    从而,也可知,block内部会对我们的对象进行copy,但是指向对象的指针不变,指针指向对象会变成新的。 

    而函数内部的局部变量被拿出去函数外部使用时,相当于 创建了一个新 的指向这个改变后对象的 指针。

    待续... ...

    以上。 

  • 相关阅读:
    Silverlight 3 Beta版的变化
    路由事件[转]
    使用Live writer写博客(转)
    Silverlight 3.0正式版RTW的发布日期
    向NBA神化人物们致敬
    英语新闻网站大全
    《Silverlight开发者期刊第一期》Silverlight开发者团队(银客帝国)
    逻辑树与可视树[转]
    微软下载中心使用Silverlight搜索
    DeskViewer基于Silverlight 2.0开发的个性相册展示系统
  • 原文地址:https://www.cnblogs.com/zhangzhang-y/p/13667632.html
Copyright © 2011-2022 走看看