Kingsly的iOS开发进阶专题iOS way, life way

block的使用

2015-12-17  本文已影响234人  cyh老崔

内容:

一.block的定义

定义变量和定义属性相同

1.定义block属性

/** 定义block属性, sumBlock为参数名 */
@property (nonatomic, copy) int (^sumBlock)(int, int);

2.定义block方法

/** 定义block方法:无参无返回值 */
    void (^myBlock)() = ^{
        NSLog(@"test");
    };
    
/** 定义block方法:有参有返回值 */
    int (^sumBlock)(int, int) = ^(int num1, int num2){
        return num1 + num2;
    };
    int sum = sumBlock(2, 3);
}

3.block作为参数


//定义block参数:参数名称写在外面(如int参数,参数名称也是写在外面)
- (void)test2:(int (^)(int, int))sumBlock{

}

4.block作为返回值


//定义block返回值
- (int (^)(int, int))test3{
    return nil;
}

typedef简化定义block

typedef void(^resultBlock)(NSArray<Person *> *arr);

二. block的使用

使用场景一:传值

控制器A modal 出控制器B, B向A传值(逆传)

/** 逆传 strNi */
@property (nonatomic, strong) NSString *strNi;

/** 逆传 block */
@property (nonatomic, strong)  void(^block)(NSString *strNi);
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    if (_block) {
        _block(_strNi);
    }
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    FanLuModalController *Bvc = [FanLuModalController alloc] init];

    //逆传
    Bvc.block = ^(NSString *str){ //str即为B控制器传过来的值
      
        NSLog(@"strNi from Bvc = %@", str);
    };
}

使用场景二: 作为参数

-- 定义block方法的类

FLCalculatorManager.h

/** calculate result */
@property (nonatomic, assign) int result;

- (void)calculator:(int(^)())block;

FLCalculatorManager.m

- (void)calculator:(int(^)())block{

    _result = block();
    
}

-- 另外一个类:调用这个calculator:方法,传入block

    FLCalculatorManager *manager = [[FLCalculatorManager alloc]init];
    
    [manager calculator:^int{
        
        return 5;
    }];

使用场景三: 作为返回值,生成链式编程(一般只有在框架中才会使用).如:

make.equalTo(superview).with.insets(padding);
注: get方法: 只要是没有参数, 且有返回值的方法,都是get方法.

- (void)viewDidLoad {
    [super viewDidLoad];
    
   //调用返回值为block的get的方法:test.
    self.test();
}

- (void(^)())test{

    return ^{
        NSLog(@"平凡而已");
    };
}
/** 最终结果 */
@property (nonatomic, assign) int result;

//返回值是一个block---CalculatorManager *(^)(int),
//这个block的返回值是一个对象---"CalculatorManager *",且这个block需要一个int参数
- (FLCalculatorManager *(^)(int))add;
- (FLCalculatorManager *(^)(int))add{
    
    //下面代码解析:
    //第一个return:返回一个返回值是当前对象的block,是代码块.这个return即是当前方法最终的return
    //第二个return:block中的return,返回当前对象
    return ^FLCalculatorManager *(int value){
        
        _result += value;
        return self;
    };
}
    FLCalculatorManager *manager = [[FLCalculatorManager alloc]init];

    //调用manager的返回值是block的get方法:add,虽然add方法没有参数,但是其block需要参数    manager.add(10).add(10).add(20);
    
    NSLog(@"result = %d", manager.result);  //result最终 == 40

三. block的内存管理

    __weak typeof(self) weakSelf = self;
__strong typeof(weakSelf) strongSelf = weakSelf;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self dismissViewControllerAnimated:YES completion:nil];
}
 // block:会对自己代码块中的,外部强指针变量强引用
    __weak typeof(self) weakSelf = self;
    
    _block = ^{
        
        // block比如做一些异步操作/延迟操作
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            NSLog(@"打印%@",strongSelf);
        });
    };

    _block();
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
   
        __block int a = 3;

// 1.如果a没有__block修饰,且已经传进方法,外面再修改a的值,block内部a的值不会改变. 
    //因为block会以const的形式将a拷贝到堆区,即block不可以修改外部变量。
// 2.默认block引用外部的局部变量,并且没有任何关键字修饰,都是值传递
// 3.如果外部变量用__block或者static修饰,就是指针传递,外面改了,里面也会改
// 4.只要是全局变量,Block中也是指针传递,可以修改变量
- (void)test{
            void(^block)() = ^{
            
            NSLog(@"%d",a);
            };
        
            a = 5;
            block(); 
   }

MRC与ARC中block的比较

上一篇 下一篇

猜你喜欢

热点阅读