文档章节

iOS开发之Block

feng_blog
 feng_blog
发布于 2015/08/31 20:52
字数 1158
阅读 28
收藏 1

1、定义

(1) Block是OC中的一种数据类型,在iOS开发中被广泛使用

(2) ^是Block的特有标记

(3) Block的实现代码包含在{}之间

(4) 大多情况下,以内联inline函数的方式被定义和使用

(5) Block与C语言的函数指针有些相似,但使用起来更加灵活

例如:

void(^demoBlock)() = ^ {

    NSLog(@"demo Block");

};

int(^sumBlock)(int, int) = ^(int x, int y) {

    return x + y;

};

格式说明:

(返回类型)(^块名称)(参数类型) = ^(参数列表) {代码实现};

如果没有参数,等号后面参数列表的()可以省略

2、常见相关面试题

Block可以使用在定义之前声明的局部变量:

int i = 10;

void(^myBlock)() = ^{

    NSLog(@"%d", i);

};

i = 100;//实际上并没效果

myBlock();

输出结果为:10

注意:

(1) 在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)

(2) 后续再对该变量的数值进行修改,不会影响Block中的数值

(3) 如果需要在block中保持局部变量的数值变化,需要使用__block关键字

(4) 使用__block关键字后,同样可以在Block中修改该变量的数值

3、当做参数传递

Block可以被当做参数直接传递:

NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    NSLog(@"第 %d 项内容是 %@", (int)idx, obj);

    if ([@"王五" isEqualToString:obj]) {

        *stop = YES;

    }

}];

说明:遍历并NSLog() array中的内容,当obj 为"王五"时停止遍历

4、使用局部变量

在被当做参数传递时,Block同样可以使用在定义之前声明的局部变量:

int stopIndex = 1;

NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    NSLog(@"第 %d 项内容是 %@", (int)idx, obj);

    if ([@"王五" isEqualToString:obj] || idx == stopIndex) {

        *stop = YES;

    }

}];

注意,默认情况下,Block外部的变量,在Block中是只读的

BOOL flag = NO;

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    if ([@"王五" isEqualToString:obj] || idx == stopIndex) {

        *stop = YES;

        flag = YES;      // 编译错误!!!

        }

}];

5__block关键字

如果要修改Block之外的局部变量需要使用__block关键字

__block BOOL flag = NO;

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    if ([@"王五" isEqualToString:obj] || idx == stopIndex) {

        *stop = YES;

        flag = YES;      // 现在可以修改了!!!

        }

}];

提示:无需使用__block关键字,在块代码中可以修改成员变量的数值(比较少用)

6传递对象

对象传递进Block的方式

NSString *stopName = @"王五";

NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    NSLog(@"第%d项内容是%@", (int)idx, obj);

    if ([stopName isEqualToString:obj] || idx == stopIndex) {

        *stop = YES;

    }

}];

为保证Block中的代码正常运行,在将stopName的指针传递给Block时,Block会自动对stopName的指针做强引用

7Block在栈区工作示意图

 

8typedef

可以使用typedef定义一个Block的类型,便于在后续直接使用

typedef double(^MyBlock)(double, double);

MyBlock area = ^(double x, double y) {

    return x * y;

};

MyBlock sum = ^(double a, double b) {

    return a + b;

};

NSLog(@"%.2f", area(10.0, 20.0));

NSLog(@"%.2f", sum(10.0, 20.0));

说明:

(1) typedef是关键字用于定义类型,MyBlock是定义的Block类型

(2) area、sum分别是MyBlock类型的两个Block变量。

 

尽管,typedef可以简化Block的定义,但在实际开发中并不会频繁使用typedef关键字。

这是因为Block具有非常强的灵活性,尤其在以参数传递时,使用Block的目的就是为了立即使用。

官方的数组遍历方法声明如下:

而如果使用typedef,则需要:

(1) typedef void(^EnumerateBlock)(id obj, NSUInteger idx, BOOL *stop);

(2) - (void)enumerateObjectsUsingBlock:(EnumerateBlock)block;

而最终的结果却是,除了定义类型之外,EnumerateBlock并没有其他用处。

9添加到数组

既然Block是一种数据类型,那么可以将Block当做比较特殊的对象

#pragma mark 定义并添加到数组

@property (nonatomic, strong) NSMutableArray *myBlocks;

int(^sum)(int, int) = ^(int x, int y) {

    return [self sum:x y:y];

};

[self.myBlocks addObject:sum];

int(^area)(int, int) = ^(int x, int y) {

    return [self area:x y:y];

};

[self.myBlocks addObject:area];

#pragma mark 调用保存在数组中的Block

int(^func)(int, int) = self.myBlocks[index];

return func(x, y);

10循环引用

@property (nonatomic, strong) NSMutableArray *myBlocks;

#pragma mark 将代码改为调用self的方法

int(^sum)(int, int) = ^(int x, int y) {

    return [self sum:x y:y];

};

[self.myBlocks addObject:sum];

#pragma mark 对象被释放时自动调用

- (void)dealloc

{

    NSLog(@"DemoObj被释放");

}

11、解除循环引用

局部变量默认都是强引用的,离开其所在的作用域之后就会被释放。

使用__weak关键字,可以将局部变量声明为弱引用

__weak DemoObj *weakSelf = self;

在Block中引用weakSelf,则Block不会再对self做强引用

int(^sum)(int, int) = ^(int x, int y) {

return [weakSelf sum:x y:y];

 

};

 

© 著作权归作者所有

feng_blog

feng_blog

粉丝 119
博文 130
码字总数 105422
作品 3
朝阳
iOS工程师
私信 提问
2018 iOS 面试题大全(补充完整版)

原文地址:2018 iOS 面试题大全 由于原作者并没有继续更新,这里我转过来继续更新下 这个栏目将持续更新--请iOS的小伙伴关注! 1、iOS 应用导航模式有哪些? 2、iOS 中持久化方式有哪些? 3、...

Theendisthebegi
2018/11/15
0
0
iOS 开发之一些著名开发者博客

国内 王巍 王巍目前在日本横滨任职于 LINE。工作内容主要进行 Unity3D 开发,8小时之外经常进行 iOS/Mac 开发。他的陈列柜中已有多款应用,其中番茄工作法工具非常棒。 博客 池建强 池建强,...

maskmale
2018/02/25
0
0
iOS精美过度动画、视频会议、朋友圈、联系人检索、自定义聊天界面等源码

iOS精选源码 iOS 精美过度动画源码(http://www.code4app.com/thread-14827-1-1.html) iOS简易聊天页面以及容联云IM自定义聊天页面的实现思路(http://www.code4app.com/thread-30348-1-1.htm...

sunnyaigd
2018/07/11
39
0
iOS与JS交互之WKWebView-WKUIDelegate协议

级别:★★☆☆☆ 标签:「iOS与JS交互」「WKWebView与JS交互」「WKUIDelegate」 作者: Xs·H 审校: QiShare团队 先解释下标题:“iOS与JS交互”。iOS指原生代码(文章只有示例),JS指前端...

QiShare
2018/09/03
0
0
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊
2018/05/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
173
4
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
5
0
Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
8
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部