iOS block

1.什么是block?它的本质是什么?

block是一个结构体,可以封装一部分代码,block存储在栈区间,内部截获的变量存储在堆区间。

struct Block_layout {
    void *isa;
    int flags;
    int reserved; 
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
};

isa:指向自身类的指针
flags:按bit位,表示一些block的附加信息
reserverd:保留变量
invoid:函数指针,block结构体定义后,实际上生成了一个函数,该函数指针指向block块
descriptor:描述block的信息,主要是size的大小,以及copy的函数指针

2.block的基础使用

1.在 Objective-C 语言中,一共有 3 种类型的 block:
_NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量。
_NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁。
_NSConcreteMallocBlock 保存在堆中的 block,当引用计数为 0 时会被销毁。

2.修饰符:copy
copy:该block创建是在栈空间的,为什么方法执行用copy保存在堆空间
weak修饰:block存储在栈空间,在另外地方调用block时,已经销毁,造成野指针

3.block的使用场景

1.传值
A类定义block,在合适的地方,执行block块,B类在某事件中将值传出
2.block作为参数
作为开发者最熟悉的场景应该是网络请求,succes和failed后将值传出
3.block作为返回值
定义一个函数,让block作为返回值,这样就可以返回一个代码块

#import "Person.h"

@implementation Person


- (void (^)(int))dogs
{
    return ^(int sums){
        NSLog(@"%d",sums);
    };
}

@end

在调用的时候,传入值

Person *per = [[Person alloc] init];
per.dogs(10);

4.链式编程
在代码块里面执行某些操作完成一些功能。返回自己,然后继续调用该函数,返回一个block,这样就可以实现masonry的链式调用效果
masnory

[View mas_makeConstraints:^(MASConstraintMaker *make) {
      make.top.equalTo(anotherView);
      make.left.equalTo(anotherView);
      make.width.mas_equalTo(@60);
      make.height.mas_equalTo(@60);
}];

eg:定义一个计算类,声明方法

- (Caculater * (^)(int))add
{
    __weak Caculater *weakSelf = self;
    return ^(int value){
        weakSelf.result = weakSelf.result + value;
        return weakSelf;
    };
}

执行计算

    Caculater *mgr = [[Caculater alloc] init];
    mgr.result = 0;
    mgr.add(5).add(6);
    NSLog(@"%d", mgr.result);

结果输出

2018-07-09 15:31:50.962559+0800 BlcokReview[1855:189577] 11

5.函数式编程
定义计算类,声明方法

- (instancetype)addBlock:(int (^)(int))blcokName
{
    _result = blcokName(_result);
    return self;
}

- (instancetype)deteBlock:(int (^)(int))blcokName
{
    _result = blcokName(_result);
    return self;
}

执行计算

Caculater *mgr = [[Caculater alloc] init];
    [[mgr addBlock:^int(int value) {
        
        value += 5;
        NSLog(@"%d", value);
        return value;
        
    }]deteBlock:^int(int value) {
        
        value -= 3;
        NSLog(@"%d", value);
        return value;
    }];

结果输出

2018-07-09 17:24:38.402167+0800 BlcokReview[2181:281962] 16
2018-07-09 17:24:38.402321+0800 BlcokReview[2181:281962] 13
4.block使用遇到的问题

1.循环引用
当一个对象持有了block后,block内部又使用了这个对象或者对象的实例变量、实例方法,这样会使block也持有这个对象,这样相互持有就是循环引用,从而导致对象无法释放引起内存泄露。
解决:
要解决循环引用只需要不要相互持有就行了,也就是说只需要一方持有就可以不让block再持有当前这个对象就OK。

你可能感兴趣的:(iOS block)