Block的用法

1、Block的应用场景
对象与对象之间的通信方式。

2、 Block用法及和Delegate的区别:
Block:只有一个闭包,只能实现单一功能, 用Block能做到的大部分情况下代理都可以实现
Delegate:一个代理对象可以签署多个方法

(通知的通信方式是1对多;代理、Blocks是1对1。三种通信方式都实现了对象之间的解耦合)

3、Block的介绍
Block是IOS4.0之后新增的一种语法结构,也成为【闭包(closure)】;
SDK4.0新增的API大量使用了Block;

4、Block的使用
(1)声明(2)实现(3)调用

4.1、Block定义

 //1.定义block
    //int (*p)(int, int);
    //caret,插入符
    //返回值 (^block变量的名字)(参数列表)
    int (^block)(int, float);
    void (^block2)(int);

    //2.block赋值
    //block = ^返回值 (参数列表 形参的名字){  
    //
    };
    block = ^(int age, float height){       
        NSLog(@"block执行了");    
        return 0;
    };   
    block2 = ^void (int a){

    };

    //1.定义和2.赋值合并
    void (^block3)(int) = ^(int age){
        NSLog(@"age");
    };

//3.block调用
    //回调
    int result = block(23, 1.80);
    NSLog(@"result = %d", result);

4.2、通过typedef声明block类型

 //typedef给一个已有的变量类型定义一个别名
 //typedef <#returnType#>(^<#name#>)(<#arguments#>);
 //typedef 返回值 (^block的类型别名)(参数列表)
 typedef int (^MyBlock)(int, float);

//typedef int MyInt;
@interface ViewController ()
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    int (^block1)(int age, float weight);

    //block1
    //int (^)(int, float)

    //定义(声明)block
    MyBlock block2;

    block2 = ^(int age, float height){
        return 0;
    };

    block2(20, 1.7);

    [UIView animateWithDuration:1 animations:^{
        ;
    }];

}

4.3、block作为参数传递

#import "ViewController.h"
typedef void(^MyBlock)(int, NSString *);
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //block赋值,作为参数传递给testBlock:
    [self testBlock:^(int age, NSString *name){      
        NSLog(@"age = %d, name = %@", age, name);       
    }];    
}
//block作为参数传递给testBlock方法
- (void)testBlock:(MyBlock)block
{
    block(20, @"张三");
}
@end

5. block和变量及内存管理
变量按作用域分为全局变量和局部变量

5.1引用局部变量时,该变量会作为常量编码到Block块中;局部变量需要使用__block修饰,才能在Block块中修改

 typedef void(^MyBlock)();

  int num = 10;
    MyBlock block = ^{
        NSLog(@"%d",num);
           };
    num = 20;

    block();

输出结果为10;

//添加__block修饰符,才可以修改
     __block int num = 10;
    MyBlock block = ^{
        NSLog(@"%d",num);
           };
    num = 20;

    block();

输出结果为20;
Block调用局部基本数据类型对象,进入到Block里面,num会变成变量,如果添加了关键字__block,那么在Block里面num就是同一个变量,我们就可以修改(也可以替换成static关键字):

__block int num = 10;
换成:static int num = 10;

5.2block引用局部对象,会retain该对象

 NSObject *obj1 = [[NSObject alloc] init];
    __block NSObject *obj2 = [[NSObject alloc] init];   
    MyBlock block = ^(int a){      
        NSLog(@"1----%@", obj1.retainCount); //obj1 retain 计数为2
        NSLog(@"2----%@", obj2.retainCount);    //obj2 计数为1
    };     
    block(20);   
    [obj1 release];
    [obj2 release];

5.3、block里引用全局变量

 NSLog(@"%ld", self.retainCount);//2
    MyBlock block = ^(int a){

        //block里引用全局变量,会把全局变量所在的对象retain
        num = 20;
        NSLog(@"%ld", self.retainCount);//3
    };

Block本身可以像对象一样copy和release,Block创建后内存分在栈上,调用copy方法,会将Block从栈移到堆上。当Block声明为全局变量时,我们应该调用Block的copy方法。

//注意此处是copy
@property(nonatomic, copy)NewBlock fBlock;

在Block(点语法)里面引用一个实例变量时,该实例对象会被retain,容易导致循环引用,循环用用会导致内存泄露。

6.Block的应用
将UIAlertView的按钮点击代理方法改为Block形式:

//  ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UIAlertViewDelegate>

- (IBAction)buttonAction:(id)sender;

@end
----------
//  ViewController.m
#import "ViewController.h"
#import "BlockView.h"

@interface ViewController ()

@end

@implementation ViewController

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

- (IBAction)buttonAction:(id)sender {

    BlockView *blockView = [[BlockView alloc] initWithTitle:@"title" message:@"message" cancelButtonTitle:@"cancel" otherButtonTitles:@"OK" clickBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {

        if (buttonIndex == 0) {
            NSLog(@"cancel");
        }else {
            NSLog(@"OK");
        }
    }];

    [blockView show];
}

----------
//  BlockView.h
#import <UIKit/UIKit.h>

typedef void(^TouchBlock)(UIAlertView *alertView,NSInteger buttonIndex);

@interface BlockView : UIAlertView

@property(nonatomic, copy)TouchBlock block;

- (id)initWithTitle:(NSString *)title
            message:(NSString *)message
  cancelButtonTitle:(NSString *)cancelButtonTitle
  otherButtonTitles:(NSString *)otherButtonTitles
         clickBlock:(TouchBlock)block;

@end

----------
//  BlockView.m
#import "BlockView.h"

@implementation BlockView

- (id)initWithTitle:(NSString *)title
            message:(NSString *)message
  cancelButtonTitle:(NSString *)cancelButtonTitle
  otherButtonTitles:(NSString *)otherButtonTitles
         clickBlock:(TouchBlock)block {

    self = [super initWithTitle:title
                        message:message
                       delegate:self
              cancelButtonTitle:cancelButtonTitle
              otherButtonTitles:otherButtonTitles, nil];

    if (self) {
        self.block = block;
    }

    return self;

}


//点击按钮后执行的协议方法
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {

    if (self.block) {
        self.block(self, buttonIndex);
    }

}
@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值