03-Block

Ø   Block 封装了一段代码,可以在任何时候执行
Ø   Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。
Ø   苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多

        1.Block的定义
     typedef 先声明类型,再定义变量进行赋值
     Typedef  int (^MySum)( int, int) ;

    Mysum sum = ^( int a, int b) {
    return a+b;
};

     在声明的同时定义变量,然后赋值
    int (^MySum)( int, int) = ^( int a, int b) {
    return a+b;
};
定义了一个叫MySum的blocks对象,它带有两个 int参数,返回 int。等式右边就是blocks的具体实现

Block 可以访问局部变量,但是不能修改。
int sum = 10;
int (^MyBlock)( int) = ^( int num) {
    sum++; // 编译报错
    return num * sum;
     };

         如果要修改就要加关键字: __block
    __block int sum = 10;
      

    


        2.Block和函数指针对比
          定义函数指针
     int (*myFn)();
     定义Block
     int (^MyBlock)( int, int);
     调用函数指针
     (*myFn)( 10, 20);
     调用Block
     MyBlock( 10, 20);




3. 利用Block传值
1.要传值的一边定义block

//定义Block别名
typedef  void(^MyBlock)( NSString *text);

//定义Block类型属性
@property( nonatomic, copy) MyBlock block;
@property ( weak, nonatomic) IBOutlet UITextField *textFiekd;

//这时block的参数就是_textFiekd.text
if ( self.delegate respondsToSelector: @selector(_block:)) {
    _block( _textFiekd. text);
}

2.接收值的一边

//实现传值方定义的Block
- ( void)viewWillAppear:( BOOL)animated {

    [ super viewWillAppear:animated];
  
    //实现block 里面的参数text就是上面的_textFiekd.text
    secondCtrl.block = ^(NSString *text) {
   
        _label.text = text;
    };
}

-------------------------------------------实现多个block传值- ------------------------------------------
1.传值方定义block,提供一个实现block事件的方法
typedef void(^fontColor)( UIColor *color);
typedef void(^fontSize)( CGFloat size);
typedef void(^more)();


@interface HeadView : UIView

@property ( nonatomic, copy) fontColor color;
@property ( nonatomic, copy) fontSize size;
@property ( nonatomic, copy) more eraser;
@property ( nonatomic, copy) more undo;
@property ( nonatomic, copy) more clear;

- ( void)blockWithColor:( fontColor)color
           andFontSize:( fontSize)size
             andEraser:( more)eraser
               andUndo:( more)undo
              andClear:( more)clear;

- ( void)blockWithColor:( fontColor)color andFontSize:( fontSize)size andEraser:( more)eraser andUndo:( more)undo andClear:( more)clear
{
    _color = color;
    _size = size;
    _eraser = eraser;
    _undo = undo;
    _clear = clear;
}

2.接收值方实现block( 注意:哪里有接收方的对象就放到哪里实现
 [headView blockWithColor:^( UIColor *color) {
        drawView. drawColor = color;
    } andFontSize:^( CGFloat size) {
        drawView. fontSize = size;
    } andEraser:^{
        [drawView eraser];
    } andUndo:^{
        [drawView undo];
    } andClear:^{
        [drawView clear];
    }];


4.利用block改写Button点击事件
1.抽出一个继承于UIButton的类,自定义按钮
2.这个类中有一个block属性(参数为UIButton类型)和一个能实现添加事件功能的方法
3.在内部利用 addTarget 实现这个方法,实现点击事件时调用block
4.在其他地方创建这个类型对象就可以调用block,来实现模仿系统添加事件的功能
------------------------------------------------------------.h-----------------------------------------------------------
//定义block别名
typedef void(^BlockBtn)( UIButton *btn);
@property ( nonatomic, copy) BlockBtn btnBlock;

// 对外提供方法(这就是对外的 addTarget 方法)
- ( void)addBlockAction:( BlockBtn)block;
------------------------------------------------------------.m-----------------------------------------------------------
- ( void)addBlockAction:( BlockBtn)btnBlock
{     //内部调用
    [ self addTarget: self action: @selector(blockAction) forControlEvents: UIControlEventTouchUpInside];
 
    //将btnBlock值存放到全局变量
    _btnBlock = btnBlock;
}

- ( void)blockAction
{
    if ( _btn != nil) {
        _btn( self);
    }
}
------------------------------------------------------------调用-----------------------------------------------------------
 [btn addBlockAction:^( UIButton *btn) {
        NSLog( @" 实现了 ");
    }];


5.利用block改写UIAlertView代理
1.抽出一个继承于 UIAlertView 的类,重写init方法
2.这个类中有一个block属性(参数为 NSInteger 类型)
3.在内部实现init方法,实现初始化时将block变量保存到自己的block属性变量
4.在其他地方创建这个类型对象就可以实现block,不用
------------------------------------------------------------.h-----------------------------------------------------------
遵守协议 UIAlertViewDelegate
//1. 定义 block 别名
typedef void (^MyBlock)( NSInteger index);

@interface MyAlertView : UIAlertView

//2. 定义 block 属性
@property( nonatomic, copy) MyBlock block;

//3. 重写初始化方法
- ( id)initWithTitle:( NSString *)title
            message:( NSString *)message
  cancelButtonTitle:( NSString *)cancelButtonTitle
  otherButtonTitles:( NSString*)otherButtonTitles
              block:( MyBlock)block;
------------------------------------------------------------.m-----------------------------------------------------------
// 重写初始化方法
- ( id)initWithTitle:( NSString *)title message:( NSString *)message cancelButtonTitle:( NSString *)cancelButtonTitle otherButtonTitles:( NSString*)otherButtonTitles block:( MyBlock)block{

    // 初始化父类初始化方法
    if( self = [ super initWithTitle:title message:message delegate: self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil])
    {
        // 将变量存放到全局
        _block = block;
    }
   
    return self;
}

// 在调用代理方法时实现 block
- ( void)alertView:( UIAlertView *)alertView clickedButtonAtIndex:( NSInteger)index{

   
    _block(index);
    
}
------------------------------------------------------------调用-----------------------------------------------------------
- ( IBAction)btn:( UIButton *)sender {
   
   
    MyAlertView *alet = [[ MyAlertView alloc] initWithTitle: @" 注意 " message: nil cancelButtonTitle: @" 取消 " otherButtonTitles: @" 确定 " block:^( NSInteger index) {
       
        if(index == 0){
           
            NSLog( @" 点击了取消 ");
        }
        else if (index == 1)
        {
            NSLog( @" 点击了确定 ");
        }
       
    }];
   
    [alet show];
}

6.MRC下的Block
//------------ block 中使用局部变量对内存的影响 ------------
1 )在 block 内部使用局部变量(非对象)的时候,会将数据拷贝一份存放在常量区域,所以不能在 block 中更改数据,如果想更改,则需要使用 __block
    __block int a = 10;

2 )在 block 中使用局部对象 ,block 会将对象计数值加一
// 如果想计数值不加以,使用 __block

//----------------------MRC----------------------------
  如果在 block 中使用全局变量,他为了持有这个变量,会将对应的对象加一
  // 使用 __block ,避免循环引用
  //block -> self -> self.view -> button -> block
 
    __block SecondViewController *this = self;
  
   [button addBlockAction:^( UIButton *button) {
      
        this-> _index = 20;    // 会将 self 加一

        [this. navigationController popViewControllerAnimated: YES];
       
    }];


7.ARC下的Block
   //block -> self -> self.view -> button -> block
    __block在ARC情况下,只能用于修饰局部变量
    // 下面写法没有作用
    __block SecondViewController *this = self;
   
    //1. 使用 __weak, 可以解决循环引用 , 但是不能访问当前类中属性
    __weak SecondViewController *weakThis = self;
   
    // 按钮的点击事件
    [button addBlockAction:^( UIButton *button) {
       
        //2. 如果想访问当前类的属性有两种方法:
       
        //(1) 如果不想吧属性公布出去,就再用 __strong 修饰一下
        __strong SecondViewController *strongThis = weakThis;
        strongThis -> _index = 30;

        //(2) 如果属性可以对外公布 , 可以把属性写成 property
        weakThis. index = 30;
     
        // 调用对象方法
        [weakThis test];
    }];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值