iOS中block的使用

作者: f1e583c455bf | 来源:发表于2017-04-21 15:38 被阅读244次

一、block简介

block代码块是在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,block是一种特殊的数据类型,其可以正常定义变量、作为参数、作为返回值,blcok还可以保存一段代码,在需要时调用。

二、block定义

block在定义时并不会执行内部的代码,只有在调用时才会执行。

//block变量的赋值:Block变量 = ^(参数列表){函数体};

1、无参数无返回值的block

//1、无参数无返回值的block
    //zqqBlock是block名 无参数可省略参数列表()
    //void (^zqqBlock)() = ^{};
    void (^zqqBlock)() = ^(){
        NSLog(@"这是无返回值无参数的block");
    };
    //调用
    zqqBlock();

2、有参数无返回值的block

    //zqqBlock是block名 NSString 是参数类型,x,y参数
    void (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        NSLog(@"这是无返回值有参数的block,参数是%@,%@",x,y);
    };
    //调用
    zqqBlock(@"a",@"b");

3、有参数有返回值的block

    //NSString是返回类型 zqqBlock是block名 NSString 是参数类型,x,y参数
    NSString* (^zqqBlock)(NSString* ,NSString*) = ^(NSString *x,NSString *y){
        return [NSString stringWithFormat:@"%@+%@",x,y];
    };
    //调用
    NSString *testStr = zqqBlock(@"a",@"b");
    NSLog(@"%@",testStr);

三、block使用

1、block重命名

利用typedef为block进行重命名

#import "ViewController.h"
@interface ViewController ()
//定义一个无返回值无参数的block
typedef void (^zqqBlock)();
//用自定义的zqqBlock声明一个block
@property (nonatomic, copy) zqqBlock abock;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 避免循环引用,用__weak修饰
    __weak ViewController *weakSelf = self;
    self.abock = ^{
        weakSelf.view.backgroundColor = [UIColor redColor];
    };
    //调用
    self.abock();
}
@end

2、block的应用场景

block声明属性要用copy修饰
因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的
<栈 :由系统维护的局部变量 是存在栈上的,其生命周期随函数的生命周期>
<堆 :由程序员申请空间地址,由程序员手动释放,生命周期受到程序员控制>
使用retain也可以,因为block的retain行为默认是用copy的行为实现的,block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。

block的使用:
  • 反向传值
//1.在NextViewController.h中声明block
#import <UIKit/UIKit.h>
typedef void (^popToNextBlock)(UIColor *color);//1.别名 传参
@interface NextViewController : UIViewController
@property (nonatomic, strong) popToNextBlock popToNextBlock;//2.声明block
@end
//2.在NextViewController.m中定义block
#import "NextViewController.h"
-(void)popToFirstBtnClick:(id)sender{
    [self.navigationController popViewControllerAnimated:YES];
    if (self.popToNextBlock){
        UIColor *color = [UIColor redColor];
        self.popToNextBlock(color);
    }
}
//上一控制器push时调用
    NextViewController *nextVc = [[NextViewController alloc]init];
    [self.navigationController pushViewController:nextVc animated:YES];
    //调用block
    __weak ViewController *weakSelf = self;
 //block的回调只对最后一次赋值有效
    nextVc.popToNextBlock = ^(UIColor *color){
        //避免循环引用,应该使用弱引用
          weakSelf.view.backgroundColor = color;
    };
  • 在方法中定义block 回调传值
//1.ZqqTool.h文件
#import <Foundation/Foundation.h>
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封装block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
//2.ZqqTool.m文件
#import "ZqqTool.h"
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
    block(str);
}
@end
//3.调用
    ZqqTool *tool = [[ZqqTool alloc]init];
    [tool zqqToolWithString:@"测试" andBlock:^(NSString *string) {
        NSLog(@"%@",string);
    }];
  • 作为参数传递
//1.ZqqSendBlock ZqqTool.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^ZqqSendBlock)(UIColor *color);
typedef void(^ZqqToolBlock)(NSString *string);
@interface ZqqTool : NSObject
//在方法中封装block
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block;
-(void)ZqqSendBlock:(ZqqSendBlock)block;
@end
//2..ZqqTool.m文件
#import "ZqqTool.h"
@implementation ZqqTool
-(void)zqqToolWithString:(NSString *)str andBlock:(ZqqToolBlock)block{
    block(str);
}
-(void)ZqqSendBlock:(ZqqSendBlock)block{
    block([UIColor redColor]);
}
@end
//3.调用
ZqqTool *tool = [[ZqqTool alloc]init];
    [tool zqqToolWithString:@"测试" andBlock:^(NSString *string) {
        NSLog(@"%@",string);
    }];
    [tool ZqqSendBlock:^(UIColor *color) {
        //
        self.view.backgroundColor = color;
    }];
注意:1、block中使用局部变量

局部变量在block中只读。变量的值在Block外改变,也不影响他在Block中的值。局部变量加__block修饰可在block代码块内被修改。

注意:2、block中循环引用问题

block用copy修饰,在self持有block中调用self或调用属于self的都会出现循环引用!解决方法:__weak Class *weakSelf = self;
而block本身不被self持有,就不会出现循环引用了。例如:UIView的动画block

[UIView animationWithDuration:0.2 animation:^{
     //
}];

相关文章

  • block编程, __block, __weak, __stro

    参考:block编程iOS __weak和__strong在Block中的使用__block & __weak &...

  • iOS Block存储域及循环引用

    系列文章:iOS Block概念、语法及基本使用iOS Block实现原理iOS Block __block说明符...

  • iOS Block实现原理

    系列文章:iOS Block概念、语法及基本使用iOS Block __block说明符iOS Block存储域及...

  • block 实用小例子

    本篇是简单介绍iOS 开发中block的使用(附demo): /* 声明一个block (返回类型)(^block...

  • ios block使用

    iOS Block的使用一 .最简单的block使用******使用block的三个步骤:1.定义block变量 ...

  • Block和Delegate使用?区别?注意事项?

    iOS Block 和 Delegate 的使用比较 1.共同的作用: Block 和 Delegate中的方法都...

  • iOS Block __block说明符

    系列文章:iOS Block概念、语法及基本使用iOS Block实现原理iOS Block存储域及循环引用 上一...

  • IOS基础Block

    参考: iOS中block的使用、实现底层、循环引用、存储位置 一:Block的使用格式和用途 1,声明和定义格式...

  • ios中Block使用

    属性block是一个函数对象,在程序运行中生成。在运行时,block创建在栈(stack)上,和其他分配在栈上的对...

  • Block 初见

    Block 初见 介绍 iOS block 的相关知识 目录 Block 背景知识 Block 使用方式 Bloc...

网友评论

    本文标题:iOS中block的使用

    本文链接:https://www.haomeiwen.com/subject/adplzttx.html