• 《Programming with Objective-C》第八章 Working with Blocks


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

    Block语法——无参数版本

    定义(Block的值)

    ^{
        NSLog(@"This is a block");
    }

    声明

    void (^simpleBlock)(void);

    类似int i;

    赋值

    simpleBlock = ^{
        NSLog(@"This is a block");    
    }

    类似i = 2;

    声明的时候定义

    void (^simpleBlock)(void) = ^{
        NSLog(@"This is a block");
    }

    类似int i = 2;

    调用

    simpleBlock();

    Block语法——带参数版本

    定义

    ^(double firstValue, double secondValue)
    {
        return firstValue * secondValue;
    }

    or

    ^double (double firstValue, double secondValue) 
    {
        return firstValue * secondValue;
    }

    声明

    double (^multiplyTwoValues)(double, double);

    赋值

    multiplyTwoValues = ^(double firstValue, double secondValue) 
    {
        return firstValue * secondValue;
    };

    声明的时候定义

    double (^multiplyTwoValues)(double, double) =
    ^(double firstValue, double secondValue) 
    {
        return firstValue * secondValue;
    };

    调用

    double result = multiplyTwoValues(2,3);

    __block修饰符

    int anInteger = 42;
    
    void (^testBlock)(void) = ^{    //此时只是Block定义,并没有执行里面的函数
        NSLog(@"Integer is: %i", anInteger);
    };
    
    anInteger = 84;
    
    testBlock();    //Block调用 输出42

    Value is captured when the block is defined.

    Block定义的时候,将值复制一份给自己,所以该值已经不受外界影响。

    __block int anInteger = 42;
    
    void (^testBlock)(void) = ^{    //此时只是Block定义,并没有执行里面的函数
        NSLog(@"Integer is: %i", anInteger);    
    };
    
    anInteger = 84;
    
    testBlock();    //Block调用 输出84

    Because anInteger is declared as a __block variable, its storage is shared with the block declaration.

    此时Block里面的值与外面的值共享同一份内存

    Block与self的恩怨情仇

    It’s important to take care when capturing self because it’s easy to create a strong reference cycle when capturing self.

    因为变量默认是__strong修饰(详见这里),所以要时刻注意在block里面对self的引用(只要出现了self关键字就算引用了,因为block会自动capture)

    假如self里面定义了一个block,那么self有一个指向block的strong指针(比如该block是self的一个strong成员变量);假如block里面使用了self,则block也默认拷贝了一个指向self的strong指针,此时形成strong reference cycle.

    解决方法:在Block前面创建一个__weak类型的指向self的指针,并在block里面使用该指针。

    例子

    __weak typeof(self) weakSelf = self;    //学习下这种写法哦 typeof(self)
    self.simpleBlock = ^{
        [weakSelf f];
    };
    ...
    self.simpleBlock();

    但是,假如Block里面又有一个Block,怎么办?最好是强引用weakSelf,此时strongSelf强引用的是weakSelf而不是self,所以不会形成strong reference cycle

    __weak typeof(self) weakSelf = self;    //学习下这种写法哦 typeof(self)
    self.simpleBlock = ^{
        [weakSelf f];
        __strong typeof(weakSelf) strongSelf = weakSelf;
        self.simpleBlock2 = ^{
            [strongSelf f];
        };
        self.simpleBlock2();
    };
    ...
    self.simpleBlock();

    图解

    一个函数最好只有一个Block参数,且最好是在最后一个

    A Block Should Always Be the Last Argument to a Method.

    It’s best practice to use only one block argument to a method.

    使用typedef定义一个block

    typedef int (^Sum)(int, int);
    Sum mySum = ^(int a, int b){
        return a+b;
    }

    or

    typedef void (^XYZSimpleBlock)(void);
    @property (copy) XYZSimpleBlock blockProperty;

    使用copy修饰block的property

    @property (nonatomic, copy) Sum mySum;
    @property (nonatomic, copy) void (^blockProperty)(void);

    非ARC下就必须写copy,because a block needs to be copied to keep track of its captured state outside of the original scope
    在ARC下写不写copy都无所谓,so it's a best practice to set copy property for block whether it's ARC or not.

  • 相关阅读:
    16. InOrder
    15. BddStyle: given-willReturn、OneLiner风格
    12. atLeastOnce、atLeast、atMost、never、only、verifyNoMoreInteractions、verifyZeroInteractions
    11. verify验证方法调用
    sqlserver数据文件变更位置
    生产上的sqlserver数据库误删或者操作不当的补救措施
    linux centos7 安装配置jdk
    linux centos7 mysql5.7 设置端口以及远程访问
    linux centos7 安装mysq5.7步骤总结
    关于Netty的那点事
  • 原文地址:https://www.cnblogs.com/chenyg32/p/4912896.html
Copyright © 2020-2023  润新知