【iOS】Block

Block 代码块 类似于指针 指向一块代码

Block是Objective C语言中的对象 但是与NSObject有所区别 Block是特殊的Objective C对象

Block 对象提供了一个使用 C 语言和 C 派生语言(如 Objective-C 和 C++)来创建表达式作为一个特别的函数。在其他语言和环境中,一个block对象有时候被称为“闭包(closure)”。在这里,它们通常被口语化为”块(blocks)”,除非在某些范围它们容易和标准 C 表达式的块代码混淆。对于闭包(closure),有很多定义,其中闭包就是能够读取其它函数内部变量的函数

【iOS】Block_第1张图片
图解

用处

1)简单的回调过程,不用再实现并调用某个函数(UIView动画)
2)代码简洁,减少冗余代码
3)与GCD结合使用 爽爆了

    //带有参数的block
    void (^YSBlock) (int ,NSString *);
    YSBlock = ^(int age,NSString *name){
        NSLog(@"年龄:%d  姓名:%@",age,name);
    };
    YSBlock(20,@"wys");

    //无参数但有返回值的block,相当于闭包
    int (^YSBlcok1)();
    YSBlock1 = ^(){
        int a = 100;
        int b = 50;
        return a+b;
    };
    int value = YSBlock();
    NSLog(@"oc --- %d",value);
    //block在加载局部变量时,会把局部变量copy成一个常量存放在block内部。并且此常量为只读的
    int a = 10;
    void (^block1) () = ^{
        NSLog(@"a的值:%d",a);
    };
    a = 5;
    block1();
    
    //如果要在block内部修改一个局部变量,必须在局部变量前加上__block关键字。
    __block int b = 5;
    void (^block2)() = ^{
        b = 10;
    };
    block2();

    //block 内部可以对实例变量 全局变量,静态变量 重新赋值

在self中对block使用了copy关键字,保留了block的引用计数,在copy的block内部,使用了self的属性,造成了self引用计数增加,此时造成了循环引用

/**
 * 1.使用property描述block时,要使用copy关键字(从栈中copy到堆中)
 * 2.在被copy的block中,如果使用对象或者对象的属性,都会造成对象引用计数增加。如果要避免此种情况,需要在对象前加__block关键字  
 * 3.__weak 
 * 4.创建一个block时,系统默认把block放在全局区 NSGlobalBlock
 * 5.当block中引用了其他变量,系统会把此block放到栈上 NSStackBlock
 * 6.在栈上的block ,对其做retain操作是不起任何作用的
 */

block使用例子

// 1. 在第二个Controller的.h文件中定义block
@property (nonatomic,copy) void(^colorBlock)(UIColor *);

// 2.在第二个Controller的.m文件中调用block
-(void)changeColor:(UIButton *)btn
{
    self.colorBlock([UIColor yellowColor]);
}

// 3.在第一个Controller的.m文件中传递block的值
-(IBAction)goNext:(id)sender
{
    NextVC * nextVc = [[NextVC alloc] init];
    __block CurrentVC * curVc = self;
    nextVc.colorBlock = ^(UIColor * color){
        curVc.view.backgroundColor = color;
    };
    [self.navigationController pushViewController:nextVc animated:YES];
}

#pragma mark - 检查网络 (HTTPManager类 -> 需要在.h中声明)
+(void)checkNetWork:(void(^)(NSInteger))blockState
{
    //网络错误
    blockState(-1);
}

//在别的类中就可以这样使用
//检查网络
[HTTPManager checkNetWork:^(NSInteger statusIndex) {
    NSLog(@"当前网络为 = %ld",statusIndex);
}];

微信公共号:iapp666666
GitHub:点此前往

你可能感兴趣的:(【iOS】Block)