大钟的ios开发之旅(6)————简单谈谈Block

原创 2016年05月30日 18:18:57

/********************************************************************************************
 * author:conowen@大钟                                                                                                                          
 * E-mail:conowen@hotmail.com                                                                                                             
 * http://blog.csdn.net/conowen                                                                                                              

 ********************************************************************************************/

1、Block的定义

Block是Objc、C、C++的一个语言级别扩充功能,Block其实就是一块代码段,你可以很方便地把一个代码段传递到不同的方法里面或者不同的类,就像传值一样方便。Block可以当做Objc里面的一个对象。(也就是说,你可以把它当做一个类似NSString的对象)


2、Block的声明

//As a local variable:

returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};

//As a property:

@property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes);

//As a method parameter:

- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;

//As an argument to a method call:

[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];

//As a typedef:

typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
上述定义来源

3、Block声明详解

其实Block的定义有点类似函数指针

引申:指针函数与函数指针的区别

a、指针函数

表示函数返回值是一个指针类型,定义如下
//类型标识符  *函数名(参数表)
int *fun(x,y);

b、函数指针

表示指向这个函数的指针变量,定义如下
<pre code_snippet_id="1695099" snippet_file_name="blog_20160527_11_8242247" name="code" class="objc">类型标识符  (*函数名)(参数表)
int (*fun) (int x,y); //函数名前面有一个星号,然后用小括号包起来
fun=funTest; /* 将funTest函数的首地址赋给指针

而Block就是
int (^fun) (int,int);


3、Block的应用场景


3.1、定义一个Block,然后输出打印信息


    int (^addFun)(int,int) = ^int(int a,int b){
    
        return a + b;
    };
    
    NSLog(@"addValue = %d",addFun(1,2));
打印消息是2016-06-01 11:27:14.191 Runtime[10910:4558911] addValue = 3

3.2、Block与Delegate的区别


这是最简单的Block使用,一般我们使用Block来做一些有趣的事情,例如代替delegate,平常我们在不同的类传值的话,一般使用delegate,虽然也能实现,但是写法比较繁琐,用Block就能很轻松实现,而且代码量少了不少。
下面的小Demo就依次对比了Delegate与Block在不同类的传值的区别

第一个ViewController的代码如下
//
//  ViewController.m
//  Runtime
//
//  Created by idealMac2 on 16/5/20.
//  Copyright © 2016年 GValley. All rights reserved.
//

#import "ViewController.h"
#import "SecondViewController.h"

@interface ViewController () <SecondViewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];
    [btn setTitle:@"open" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(openAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)openAction:(id)sender{
    NSLog(@"openAction");
    SecondViewController *secondViewController = [SecondViewController new];
    secondViewController.callBackValue =  ^ void (NSString *str){
        NSLog(@"Block str = %@",str);
     
    };
    secondViewController.delegate = self;
    [self presentViewController:secondViewController animated:YES completion:nil];

}

#pragma mark SecondViewControllerDelegate
- (void)closeAction:(NSString *) str{

    NSLog(@"delegate str = %@",str);
}

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

@end


第二个ViewController的头文件如下
//
//  SecondViewController.h
//  Runtime
//
//  Created by idealMac2 on 16/6/1.
//  Copyright © 2016年 GValley. All rights reserved.
//

#import <UIKit/UIKit.h>
//声明delegate
@protocol SecondViewControllerDelegate <NSObject>

@optional
- (void)closeAction:(NSString *) str;

@end

@interface SecondViewController : UIViewController
//声明Block
@property (nonatomic,copy) void(^callBackValue)(NSString *);

@property (nonatomic,weak) id<SecondViewControllerDelegate>  delegate;
@end


第二个ViewController的实现文件如下


//
//  SecondViewController.m
//  Runtime
//
//  Created by idealMac2 on 16/6/1.
//  Copyright © 2016年 GValley. All rights reserved.
//

#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];
    [btn setTitle:@"close" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(closeAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)closeAction:(id)sender{

    
    NSString *strA = @"closed";
    //Block的方式
    self.callBackValue(strA);
    
    //Delegate的方式
    if (self.delegate && [self.delegate respondsToSelector:@selector(closeAction:)]) {
        [self.delegate closeAction:strA];
    }
   
    [self dismissViewControllerAnimated:YES completion:nil];
 
}




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

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


打印消息如下

2016-06-01 12:10:31.211 Runtime[10959:4573582] block str = closed

2016-06-01 12:10:31.211 Runtime[10959:4573582] delegate str = closed


4、Block与外部变量的关系

我们知道,Block有一个神奇之处,它可以直接使用Block之外的变量,如下面的代码。
    int c = 0;
   
    int (^addFun)(int,int) = ^int(int a,int b){
        return a + b + c;
    };
   
    
    NSLog(@"addValue = %d",addFun(1,2));

但是如果要修改外部变量,就会出现无法修改的问题,同时,使用外部变量,也会存在引起循环引用的问题。

4.1、如何修改Block外部变量


解决这个问题有两种方法:
一种是C语言的方法,因为C语言中的静态变量、静态全局变量,全局变量是允许Block修改其值的。因为“全局变量” 和“ 全局静态变量” 由于作用域是全局,所以在 Block 内访问和读写这两类变量和普通函数没什么区别。但是“ 静态变量” 作用域在 block 之外,那Block是怎么对它进行读写呢?其实“静态变量” 是通过指针传递,将变量传递到 Block 里面,所以可以修改变量值。普通的非全局变量,都是通过传值进去Block里面,当然无法修改这个变量的值。

如下面的代码
    static int c = 0;//静态变量
   
    int (^addFun)(int,int) = ^int(int a,int b){
        c = 1;
        return a + b + c;
    };
   
    
    NSLog(@"addValue = %d",addFun(1,2))

还有一种方法就是通过在变量外部加上“__block”说明符,其实加了__Block之后,这个变量就变成了一个结构体指针变量,这个原理和静态变量一样,由传值方式改为指针传递,所以就可以更改变量了。
如下所示
    __block int c = 0;
   
    int (^addFun)(int,int) = ^int(int a,int b){
        c = 1;
        return a + b + c;
    };
   
    
    NSLog(@"addValue = %d",addFun(1,2));



4.2、如何避免Block的循环引用



版权声明:本文为博主原创文章,未经博主允许不得转载。

大钟的ios开发之旅(5)————简单谈谈RunLoop

/********************************************************************************************  * aut...
  • conowen
  • conowen
  • 2014年11月07日 15:45
  • 16754

大钟的ios开发之旅(7)————简单谈谈GCD

待编辑
  • conowen
  • conowen
  • 2016年05月31日 16:57
  • 1442

大钟的ios开发之旅(3)————聊聊Runtime的objc_mesgSend

一、前言       ios开发中,@property的修饰就有很多的修饰词,如retain、assign、strong、weak、nonatomic等等,而这些修饰词在ARC模式下与非ARC模式下也...
  • conowen
  • conowen
  • 2014年11月04日 17:48
  • 5445

大钟的ios开发之旅(4)————聊聊Runtime 中的类对象

在AppDelegate.m中的生命周期函数中设置
  • conowen
  • conowen
  • 2014年11月04日 18:40
  • 2582

iOS 对于block的理解

block是对象,它封装了一段代码,这段代码可以在任何时候执行。block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:block是inli...
  • worldzhy
  • worldzhy
  • 2014年12月11日 01:22
  • 17302

大钟的ios开发之旅(8)————如何优化UITableView

/********************************************************************************************  * aut...
  • conowen
  • conowen
  • 2016年06月02日 14:46
  • 1531

大钟的ios开发之旅(★firecat入门推荐,iOS开发者账号申请★)

大钟的ios开发之旅(1)————ios开发的准备工作,申请开发者账号和证书 http://blog.csdn.net/conowen/article/details/40740435 大钟的i...
  • libaineu2004
  • libaineu2004
  • 2015年05月14日 10:44
  • 394

iOS开发——Block简单传值

因为事件其实是发生在第二个界面,按下确定按钮时,所以我们在第二个界面,声明并定义Block。 typedef void(^SelectedRoomBlock)(NSString *roomName);...
  • wanglei0918
  • wanglei0918
  • 2017年07月10日 11:49
  • 79

大钟的ios开发之旅(2)————聊聊Runtime 定义

/********************************************************************************************  * aut...
  • conowen
  • conowen
  • 2014年11月03日 15:30
  • 2708

IOS开发 block(代码块)基本使用

1. block基本概念:(开篇废话) Block是C级别的语法和运行时特性。Block比较类似C函数,但是Block比之C函数,其灵活性体现在栈内存、堆内存的引用。Block是苹果推荐的类型,效率...
  • zhuohong_xiao
  • zhuohong_xiao
  • 2015年04月22日 22:45
  • 1495
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:大钟的ios开发之旅(6)————简单谈谈Block
举报原因:
原因补充:

(最多只允许输入30个字)