Block简单使用

一、Block简介

Block是ios4.0引入的基于c语言函数的一种回调机制,也可以说Block是带有自动变量(局部变量)的匿名函数。具体block是怎么实现的可以去看 唐巧的博文

二、Block的使用

1、Block类型
  • 无参数无返回值的Block
  • 有参数无返回值的Block
  • 有参数有返回值的Block
2、创建Block
  • 单独定义:返回值类型(^block变量名)(形参列表) = ^(形参列表) {};
  • 调用:block变量名(实参);
  • 作为OC方法参数的定义:返回值类型(^)(参数列表)block变量名
 例:int (^myBlock)(int a, int b) = ^(int x, int y){
   return x + y;
 }
 myBlock(a,b);//跟C语言调用函数一样
 - (void)method:(void(^)()myBlock){};//block作为参数 
3、Block注意事项
  • Block是放在内存堆里面的
  • Block不是对象,所以Block作为属性需要使用copy修饰
  • 默认情况下,Block内部不能修改外面的局部变量
  • Block内部可以修改使用__block修饰的局部变量
int num = 10;
__block int value = 10
void (^myBlock)(int a) = ^(int y){
    num = 20; 
    value = 20;
};//
myBlock();
NSLog(@"num == %d value == %d",num,value);//这里num = 10;value = 20;

3、Block的具体使用

1、界面传值

使用block进行两个界面的传值,代码比起代理来说简洁很多。下面的代码是连个控制器之间的传值,当TowController返回OneController时就会修改OneController的控制器View的背景颜色,以及将TwoController界面UITextField里面输入的值传回第一个界面。

OneController的代码

#import "OneController.h"
#import "TwoController.h"

@interface OneController ()
@property (weak, nonatomic) IBOutlet UITextField *passWord;

@end

@implementation OneController

- (void)viewDidLoad {
    [super viewDidLoad];
    

    
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    TwoController *twoVc = [self.storyboard instantiateViewControllerWithIdentifier:@"TwoController"];
    
    twoVc.myblock = ^(NSString *string,UIColor *color){
    //括号里面的代码只有当TwoController点击事件触发,myBlock调用时,这段代码才会执行
        self.view.backgroundColor = [UIColor blueColor];
        self.passWord.text = string;//
    };
    [self presentViewController:twoVc animated:YES completion:^{
        NSLog(@"LOG");
    }];
}


TwoController的代码

#import "TwoController.h"
typedef void(^myBlock)(NSString *passWord, UIColor *bgColor);//

@interface TwoController ()

@property (nonatomic, copy) myBlock myblock;

@property (weak, nonatomic) IBOutlet UITextField *passWord;


@end

@implementation TwoController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
   
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UIColor *color = [UIColor redColor];
    self.myblock(self.passWord.text,color);//调用block并传值
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"TWO");
    }];
}
2、修改UIButton的点击事件

为什么要用block来重写按钮的点击事件?因为这样可以使代码简洁,点击事件直接放在block里面,不用在重新再定义一方法。

自定义UIButton点击事件


#import "XSButton.h"

@interface XSButton (){
   buttonBlock _block;
}

@end


@implementation XSButton

- (void)hand:(buttonBlock)buttonAction{
   
   _block = buttonAction;//赋值
   [self addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
}
//点击事件
- (void)buttonAction{
   
   if (_block) {//判断_block是否存在
       
       _block();//调用代码块
   }
}

控制器调用:

#import "ViewController.h"
#import "XSButton.h"

@interface ViewController ()


@property(nonatomic, strong)XSButton *button;

@end

@implementation ViewController


- (XSButton *)button{
    if (!_button) {
        _button = [XSButton buttonWithType:UIButtonTypeCustom];
        [_button setTitle:@"按钮" forState:UIControlStateNormal];
        _button.frame = CGRectMake(100,200,100, 100);
        _button.backgroundColor = [UIColor redColor];
        [_button hand:^{
            NSLog(@"点击了----");//按钮点击事件
        }];
    }
    return _button;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view addSubview:self.button];
    // Do any additional setup after loading the view, typically from a nib.
}

4、Block的内存管理(使用时引起的循环引用)

1、MRC:当Block内部使用局部对象时,局部对象的引用计数会加1; 当Block内部使用全局的对象时,全局对象的引用计数不会加1,但是持有全局对象的对象(当前对象self)引用计数会加1;

2、ARC:当block为当前对象的成员变量时(当前对象(self)持有block)

  • block内部使用当前对象的实例变量时会造成循环引用
  • block内部使用当前对象的实例方法也会造成循环引用

解决循环引用方法:使用__weak关键字修饰,weakSelf使用了弱引用,self也就使用了弱引用,block内部也就不会再持有当前对象(self)

__weak typeof(self)wekSelf = self;//ARC
__block typeof(self)wekSelf = self;//MRC

下面代码示例解决循环引用

#import "MyBlock.h"
typedef void(^myBlock)();//定义一个block别名

@interface MyBlock ()
@property (nonatomic, copy)myBlock block;//创建一个block变量

@property (nonatomic, strong)NSObject *obj;

@end
@implementation MyBlock

//循环引用,调用这个方法时,- (void)dealloc;不会调用
- (void)circularReference{
  //当双方相互持有彼此时就会造成循环引用
  self.block = ^{
      NSLog(@"%@",self.obj);//当前d对象(self)持有self.block,这句代码又让self.block持有了当前对象(self)
      
      [self method];//调用self的实例方法也会造成循环引用
  };
}

//解决循环引用,调用这个方法时,- (void)dealloc;会调用
- (void)toooo{  
  __weak typeof(self)weakSelf = self;
  self.block = ^{
      NSLog(@"%@",weakSelf.obj);
      
      [weakSelf method];
  };
  
  self.block();
  
  //不会造成循环引用,myBlock为局部变量。
  myBlock myBlock = ^{
      NSLog(@"%@",self.obj);
  };
  myBlock();
  
}

- (void)dealloc{
  NSLog(@"对象销毁了");
}
- (void)method{
  
}


转载于:https://my.oschina.net/u/2432377/blog/738488

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值