前言

  • Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递。Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。Block 是 C 语言的,类似于一个匿名函数,它和传统的函数指针很类似,但是 Block 是 inline(内联函数)的,并且默认情况下它对局部变量是只读的。

  • 苹果官方建议尽量多用 Block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多。

  • Block 语法

    	// Block as a local variable
    returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; // Block as a property
    @property (nonatomic, copy) returnType (^blockName)(parameterTypes); // Block as a method parameter
    - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName; // Block as an argument to a method call
    [someObject someMethodThatTakesABlock: ^returnType (parameters) {...}]; // Block as typedef
    typedef returnType (^TypeName)(parameterTypes);
    TypeName blockName = ^returnType(parameters) {...};

1、Block 的使用

1.1 Block 的定义

  • Block 的简单定义

    	// 定义 Block
    /*
    定义了一个名叫 MySum 的 Block 对象,它带有两个 int 型参数,返回 int 型。等式右边就是 Block 的具体实现,大括号后需加分号
    */
    int (^MySum)(int, int) = ^(int a, int b){ return a + b;
    }; // 调用 Block
    int sum = MySum(10, 12);
  • Block 数据类型的定义

    	// 定义 block 数据类型 MyBlock
    typedef int (^MyBlock)(int, int); // 定义 MyBlock 的变量
    MyBlock myblock; // 实现 MyBlock 的变量 1
    myblock = ^(int a, int b){ return a + b;
    }; // 调用 MyBlock 的变量 1
    int sum = myblock(10, 12); // 实现 MyBlock 的变量 2
    myblock = ^(int a, int b){ return a - b;
    }; // 调用 MyBlock 的变量 2
    int minus = myblock(13, 2);

1.2 Block 访问局部变量

  • Block 可以访问局部变量,但是不能修改,如果要修改需加关键字 __block(双下划线)。

    	// 这样定义时,局部变量 sum 只能读取值不能修改,编译时会报错
    // int sum = 10; // 这样定义时,局部变量 sum 既可以读取值又能修改
    __block int sum = 10; int (^MyBlock)(int) = ^(int a){ // 对局部变量值修改
    sum ++; // 读取局部变量的值
    return a * sum;
    }; int result = MyBlock(5);

2、Block 的回调

2.1 Block 回调使用

	// Block1.h

		// block 属性变量定义
/*
要使用 copy 类型,格式:@property (nonatomic, copy) 返回值类型 (^变量名) (参数类型列表);
*/
@property (nonatomic, copy) void (^completion) (NSString *); // 调用 block 代码段声明
- (void)useBlock; // Block1.m // 调用 block 代码段
- (void)useBlock { // 设置 block 的回调值 // 判断是否设置了 block
if (self.completion != nil) { // 设置回调值
self.completion(@"hello world");
}
} // Block.m #import "Block1.h" Block1 *block = [[Block1 alloc] init]; // 设置 block 代码段
block.completion = ^(NSString *str) { // 结果:string = @"hello world"
NSString *string = str;
}; // 调用 block 代码段
[block useBlock];

2.2 Block 回调封装

	// Block2.h

		// block 方法参数定义

		// 类方法定义
+ (Block2 *)blockWithCompletion:(void (^) (NSString *)) completion; // 调用 block 代码段声明
- (void)useBlock; // Block2.m // block 属性变量定义 // 要使用 copy 类型,格式:@property (nonatomic, copy) 返回值类型 (^变量名) (参数类型列表);
@property (nonatomic, copy) void (^completion) (NSString *); // 调用 block 代码段
- (void)useBlock { // 设置 block 的回调值 // 判断是否设置了 block
if (self.completion != nil) { // 设置回调值
self.completion(@"hello world");
}
} // 类方法实现
+ (Block2 *)blockWithCompletion:(void (^)(NSString *))completion { Block2 *bl = [[Block2 alloc] init]; // 设置属性的值
bl.completion = completion; return bl;
} // Block.m #import "Block2.h” // 设置 block 代码段
Block2 *block = [Block2 blockWithCompletion:^(NSString *str) { // 结果:string = @"hello world"
NSString *string = str;
}]; // 调用 block 代码段
[block useBlock];

3、Block 属性定义中为什么使用 copy 修饰

  • ARC 开发的时候,编译器底层对 block 做过一些优化,使用 copy 修饰可以防止出现内存泄漏。

  • 从内存管理的角度而言,程序员需要管理的内存只有堆区的。如果用 strong 修饰,相当于强引用了一个栈区的变量。

  • 而使用 copy 修饰,在设置数值的时候,可以把局部变量从栈区复制到堆区。

    	// 用 copy 修饰定义属性
    @property (nonatomic, copy) void (^myTask)(); // 定义,myBlock 是保存在栈区的,出了作用域,就应该被销毁
    void (^myBlock)() = ^ { NSLog(@"hello");
    }; // 用属性记录
    self.myTask = myBlock; // 执行
    self.myTask();

4、循环引用

  • 在 Block 中调用 self 容易产生循环引用,无法释放对象,在程序中可以使用析构方法判断是否产生了循环引用。

    	@implementation ViewController
    
    	// 在 Block 中调用 self 容易产生循环引用
    [[QWebImageManager sharedManager] downloadImage:self.urlStr completion:^(UIImage *image) {
    self.image = image;
    }]; @end
    	// 判断是否存在循环引用,无法释放时即存在循环引用
    - (void)dealloc {
    NSLog(@"成功退出");
    }
  • 可以使用关键字 __weak 声明一个弱变量,或者为属性指定 weak 特性。如:

    	@implementation ViewController
    
    	// 弱引用 self,typeof(self) 等价于 ViewController
    __weak typeof(self) weakSelf = self; [[QWebImageManager sharedManager] downloadImage:self.urlStr completion:^(UIImage *image) {
    weakSelf.image = image;
    }]; @end

iOS - OC Block 代码块的更多相关文章

  1. OC Block(代码块)

    #import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...

  2. iOS:使用block代码块实现事件处理过程中的回调

    block是什么,这里就不多加强调了,它的优点: 第一:执行效率高,速度快 第二:使用起来比代理简单,省却不少代码,增强代码美感 有一些小的知识点要强调一下: 第一点:它类似于一个匿名函数,也跟jav ...

  3. ios开发 block语句块

    ios开发 block语句块 1.block 理解为匿名函数 2.block变量的定义 //定义block变量,^表示定义block //技巧:函数名左右加括号,在函数名前面在加^ void (^bl ...

  4. block(代码块)的介绍以及使用方法和变量之间的关系

    http://blog.csdn.net/menxu_work/article/details/8762848 block(代码块)的介绍以及使用方法和变量之间的关系 block(代码块)的介绍以及使 ...

  5. block代码块介绍

    关于block的简单介绍 什么是block? Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象:它也很像C++中的 ...

  6. Block代码块中使用局部变量注意点

    第一次写代码遇到报这个错,实在是想不通为什么,按常理应该是不会有问题,报错的呀??纠结了一会之后只好仔细查看报错原因咯,原来是: 当我们在block代码块中使用局部变量时,就会很容易出现如图的错误. ...

  7. IOS学习4——block代码块

    本文转载自:iOS开发-由浅至深学习block 一.关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想 ...

  8. iOS学习之代码块(Block)

    代码块(Block) (1)主要作用:将一段代码保存起来,在需要的地方调用即可. (2)全局变量在代码块中的使用: 全局变量可以在代码块中使用,同时也可以被改变,代码片段如下: ;//注意:全局变量 ...

  9. IOS Block代码块的定义与使用

    代码块的本质是和其他的变量类似,不同的是,代码块存储的数据是一个函数体.使用代码块,你可以像调用其他标准函数一样的调用,可以传入参数,并得到返回值.     脱字符是代码块的语法标记.下图表示代码块的 ...

随机推荐

  1. Dynamics AX 2012 R2 Business Connector Error

    6.0: AxCryptoClient - New encryption key created 6.0: Unable to InitializeSession. 6.0: No built-in ...

  2. 使用磁盘为Linux添加swap

    一.SWAP 说明 1.SWAP 概述 当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放 ...

  3. DECODE函数

    DECODE函数相当于一条件语句(IF),它将输入数值与函数中的参数列表相比较,根据输入值返回一个对应值.函数的参数列表是由若干数值及其对应结果值组成的若干序偶形式.当然,如果未能与任何一个实参序偶匹 ...

  4. HDU 5795:A Simple Nim(博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=5795 A Simple Nim Problem Description   Two players take t ...

  5. ZOJ 3866 - Cylinder Candy

    3866 - Cylinder Candy Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu ...

  6. Poj(3615),Floyd,最大值中的最小值

    题目链接:http://poj.org/problem?id=3615 题意:大致题意:有N个木桩,和M个木桩对之间的高度差(从x跳到y需要往上跳的高度).从x跳跃到y的路径消耗的体力值是路径中的一个 ...

  7. Linux下缓冲区溢出攻击的原理及对策(转载)

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...

  8. 驱动之module_init/module_exit

    在前面helloworld的编写里面,我们使用了两个宏分别是module_init和module_exit,这里分析下为什么使用这两个宏. 在写模块的时候有两个特殊的函数,分别是init_module ...

  9. javascript + jquery函数大全

    JAVASCRIPT Array 函数   array创建数组 concat()连接两个或更多的数组,并返回结果. join()把数组中所有元素组成字符串. pop()删除并返回数组的最后一个元素 s ...

  10. Prompt isNaN 数组 function DOM window.open/close/location/history

    1.prompt的利用 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Defa ...