iOS开发block用法


源码下载   

浅谈block用法

对于block他用着确实方便,好多人都很迷茫,这里写了一个Demo讲解block的用法

好多人都认为block是用于后一个界面向前一个界面传值用的,其实更具体的说是常用来界面之间的传值,其实只要需要传值无论是view之间还是controller之间还是view与controller之间都可以用block,当传值比较少时用block比使用代理更方便.

block创建后都在栈区存放的,block的语义特性必须用copy,通过copy可以将block从栈区放到堆区,保证每次使用block时block都存在,因此我们使用时常常要定义属性,使用属性是为了保存该block变量

如下举个例子讲解

首先在工程中创建两个类BlockViewController和BlockView

在BlockView中只是为了创建几个button,在BlockViewController中使用,可以减少BlockViewController的代码任务量,但是BlockView中只有一个实例变量button是,并且在延展中定义的,外部无法访问到,当我们为button添加点击触发事件就需要获得button的tag值,这时就要把所点击button的tag获取到,来为不同的button添加响应事件


BlockView.h中定义一个block变量和一个方法,方法的参数是block类型的

#import 

//第一步:声明block
typedef void(^ButtonActionBlock)(NSInteger tag);

@interface BlockView : UIView
-(void)buttonActionBlock:(ButtonActionBlock)didClickButton;


@end

在BlockView.m中
#import "BlockView.h"

@interface BlockView ()
//Block
//block创建后都在栈区存放的,block的语义特性必须用copy,通过copy可以将block从栈区放到堆区,保证每次使用block时block都存在
@property (nonatomic, copy) ButtonActionBlock buttonActionBlock;
@property (nonatomic, strong) UIButton *button;

@end


@implementation BlockView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CGFloat x = 5;
        CGFloat y = 5;
        CGFloat width = 65;
        CGFloat height = 40;
        //创建button
        for (int i = 0; i < 4; i ++) {
            self.button = [UIButton buttonWithType:(UIButtonTypeSystem)];
            self.button.frame = CGRectMake(x + i * (width + 10), y, width, height);
            self.button.tag = 100 + i;
            self.button.backgroundColor = [UIColor cyanColor];
            self.button.layer.cornerRadius = 5;
            self.button.layer.masksToBounds = YES;
            [self.button setTitle:[NSString stringWithFormat:@"%d",i] forState:UIControlStateNormal];
            [self.button addTarget:self action:@selector(handleButton:) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:_button];
        }
    }
    return self;
}

//处理button的点击事件,将tag值传给block的参数回调block
-(void)handleButton:(UIButton *)button
{
    NSLog(@"3");
    NSInteger tag = button.tag;
   //第二步,回掉block
   self.buttonActionBlock(tag),NSLog(@"6");
    NSLog(@"7");
    
}

//该方法中self.buttonActionBlock = didClickButton;执行后会调用属性buttonActionBlock的setter方法,将block变量didClickButton传给setter方法的参数
-(void)buttonActionBlock:(ButtonActionBlock)didClickButton
{
    NSLog(@"1");
    NSLog(@"-----------didClickButton = %p",didClickButton);
    self.buttonActionBlock = didClickButton;
    
}

//重写属性buttonActionBlock的setter方法,在此重写setter方法目的是为了表明该方法是把传进来的block变量进行深拷贝,拷贝到了堆区,并赋给了实例变量buttonActionBlock,使我们在任何时候都能使用block变量(block的创建后在栈区,出了方法就被回收,无法再使用)
- (void)setButtonActionBlock:(ButtonActionBlock)buttonActionBlock
{
    NSLog(@"2");
    if (_buttonActionBlock != buttonActionBlock) {
        NSLog(@"++++++++buttonActionBlock = %p",buttonActionBlock);
        _buttonActionBlock = [buttonActionBlock copy];
    }
}




@end

 
  


BlockViewController.m文件中导入BlockView.h文件

BlockViewController.m文件中代码实现

#import "BlockViewController.h"
#import "BlockView.h"
// 获取RGB颜色
#define RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]

@interface BlockViewController ()

@property (nonatomic, strong) UIImageView *YJFImageView;

@end

@implementation BlockViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = RGBA(252, 230, 201, 1.0);
    BlockView *blockView = [[BlockView alloc] initWithFrame:CGRectMake(10, 0, 320 - 20, 50)];
    blockView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:blockView];
    //BlockView的对象blockView调用其方法buttonActionBlock:
   //第三步,调用block
   [blockView buttonActionBlock:^(NSInteger tag) {
        //block的实现
        NSLog(@"4");
        [self handleButton:tag];
        NSLog(@"5");
        
    }];
    [self createView];
}

//处理自定义toolBar的点击事件
-(void)handleButton:(NSInteger)tag
{
    
    switch (tag) {
            //...按钮
        case 100:
        {
            self.YJFImageView.image = LOADIMAGE(@"2", @"jpg");
        }
            break;
            
            //...按钮
        case 101:
        {
            self.YJFImageView.image = LOADIMAGE(@"5", @"jpg");
        }
            break;
            
            //...按钮
        case 102:
        {
            self.YJFImageView.image = LOADIMAGE(@"6", @"jpg");
        }
            break;
            
            //...按钮
        case 103:
        {
            self.YJFImageView.image = LOADIMAGE(@"4", @"jpg");
        }
            break;
            
        default:
            break;
    }
}

-(void)createView
{
    self.YJFImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 52, 320 - 20, 568 - 64 - 75)];
    self.YJFImageView.image = LOADIMAGE(@"8", @"jpg");
    self.YJFImageView.userInteractionEnabled = YES;
    
    
    [self.view addSubview:_YJFImageView];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

通过程序运行控制台输出结果如下:

点击button前:

由此结合代码实现中打的log可以看出

didClickButton和传入属性的setter方法的参数是一个地址,则
 ,BlockView.m文件中 
  
buttonActionBlock:方法中把didClickButton拷贝了一份到栈区,赋值给实例变量_buttonActionBlock
 
  

点击button后:

iOS开发block用法_第1张图片

结合代码实现中打的log可以看出整个Block的执行过程,也可以通过打断的查看Block的执行过程









你可能感兴趣的:(UI,block,回调)