zoukankan      html  css  js  c++  java
  • block

    block是匿名函数
    block的类型:void (^)()
    ^只是用来表示这是一个block对象,和函数指针中的*的作用一样,只是一个标识符

    block正常储存在栈区和全局区 用copy就会储存在堆区
    注意在MRC下使用copy,在ARC下使用,也可以使用strong用来修饰,在strong中碰到block会自动有copy到堆内存的功能,但是苹果官方还是推荐使用copy

    MARK: 这里值得一提的是大部分的时候NSString的属性都是copy,那修饰NSString时候copy与strong的情况下到底有什么区别呢?

    这是因为

    对源头是NSMutableString的字符串,retain仅仅是指针引用,增加了引用计数器,这样源头改变的时候,用这种retain方式声明的变量(无论被赋值的变量是可变的还是不可变的),它也会跟着改变;而copy声明的变量,它不会跟着源头改变,它实际上是深拷贝。

    对源头是NSString的字符串,无论是retain声明的变量还是copy声明的变量,当第二次源头的字符串重新指向其它的地方的时候,它还是指向原来的最初的那个位置,也就是说其实二者都是指针引用,也就是浅拷贝。

    另外说明一下,这两者对内存计数的影响都是一样的,都会增加内存引用计数,都需要在最后的时候做处理。

    其 实说白 了,对字符串为啥要用这两种方式?我觉得还是一个安全问题,比如声明的一个NSString *str变量,然后把一个NSMutableString *mStr变量的赋值给它了,如果要求str跟着mStr变化,那么就用retain;如果str不能跟着mStr一起变化,那就用copy。而对于要把 NSString类型的字符串赋值给str,那两都没啥区别。不会影响安全性,内存管理也一样。

    详见链接:http://blog.csdn.net/itianyi/article/details/9018567

    首先来一个简单的block的问题

    复制代码
    复制代码
            int a = 10;
            void (^myBlock)() =
            ^{
                NSLog(@"a = %d",a);
                
            };
            myBlock();
    复制代码
    复制代码

    第一问:在block块内部能否访问到外部变量    答案是:可以

    复制代码
    复制代码
            int a = 10;
            void (^myBlock)() =
            ^{
                NSLog(@"a = %d",a);
                
            };
            myBlock();
    复制代码
    复制代码

    第二问:在block块内部能否改变外部变量的值    答案:不可以,局部变量存放在栈区,block存放在堆区 ,调用的时候根本找不到

    复制代码
    复制代码
            int a = 10;  // 局部变量存放在栈区
            void (^myBlock)() =   // 存放在堆区
            ^{
                a = 100;   // 以const的方式进行值拷贝
                NSLog(@"a = %d",a);
                
            };
            myBlock();
    复制代码
    复制代码

    第三问:block内部访问a和外部变量a的地址是否一样   答案:答:不一样,外部存放在栈区,内部a存放在堆区

    复制代码
    复制代码
    int a = 10;
            NSLog(@"外部 a = %p", &a);  // 栈区地址
            void (^myBlock)() =
            ^{
                NSLog(@"内部 a = %p", &a);  // 堆区地址
            };
            myBlock();
    复制代码
    复制代码

    打印结果

    2016-06-02 15:14:26.828 OCLesson7Test[21467:387054] 外部 a = 0x7fff5fbff7dc
    2016-06-02 15:14:26.829 OCLesson7Test[21467:387054] 内部 a = 0x1003000e0
    Program ended with exit code: 0

    第四问:如果我想在block内部改变外部的值该怎么办?    答案:答:方法1:把外部的变量定义为全局变量  方法2: 如果是局部变量,在局部变量定义前使用__block修饰

    复制代码
    复制代码
            static int a = 10;
            // 或者
            // __block int a = 10;
    
            void (^myBlock)() =
            ^{
                a = 100;
                NSLog(@"%d", a);
            };
            myBlock();
            NSLog(@"%d", a);
    复制代码
    复制代码

    第五问:此时a的值是多少?     答案:修改后的值

    设置两个controller,点击第一个controller的右按钮push到第二个controller,在第二个controller中声明无参无返block属性,实现改变view的颜色;

    实现block
        

    在controller中定一block属性
    实现block的时候,如果block里面需要使用当前控制器对象,不可以直接使用self否则
    会引起循环引用

    使用__weak修饰防止循环引用
    __block是在MRC中使用的

    复制代码
    复制代码
     __weak typeof (self) secondVC = self;
        
        self.block = ^void() {
            NSLog(@"这是block的实现");
            secondVC.view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 256.0 green:arc4random() % 256 / 256.0 blue:arc4random() % 256 / 256.0 alpha:1];
        };
        // 调用
        self.block();
    复制代码
    复制代码

    控制器销毁会走这个方法

    - (void)dealloc {
    //    [super dealloc];  mrc必须写,ARC不写
        NSLog(@"第二个控制器被销毁");
        
    }
  • 相关阅读:
    ddd
    对Map按key和value分别排序
    两端通信
    WinDBG调试.NET程序示例
    FAQ:仓储实现为什么在基础设施层?
    Please Send Me a Card
    Web API 入门指南
    Node.js
    聊天工具mychat
    C语言面试问答5
  • 原文地址:https://www.cnblogs.com/ivonne/p/5705283.html
Copyright © 2011-2022 走看看