iOS开发之Block

摘要:
1.定义(1)Block是OC中的一种数据类型,在iOS开发中广泛使用(2)^是Block的唯一标记(3)Block的实现代码包含在{}之间(4)在大多数情况下,Block是以内联函数的方式定义和使用的(5)Block与C语言中的函数指针有些相似,但使用起来更灵活,例如:void(^demoBlock)()=^{NSLog(@“demoBlock”);};int(^sumBlock)(int,i

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在栈区工作示意图

iOS开发之Block第1张

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的目的就是为了立即使用。

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

iOS开发之Block第2张

而如果使用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被释放");

}

iOS开发之Block第3张

11、解除循环引用

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

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

__weak DemoObj *weakSelf = self;

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

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

return [weakSelf sum:x y:y];

};

iOS开发之Block第4张

免责声明:文章转载自《iOS开发之Block》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇.NET中的Func委托用法JAVAWEB应用模块(一)登录模块下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

IOS开发-使用Storyboard进行界面跳转及传值

主题StoryBoard 前言:苹果官方是推荐我们将全部的UI都使用Storyboard去搭建,Storyboard也是一个非常成熟的工具了。 使用Storyboard去搭建全部界面,我们能够非常迅捷地搭建出复杂的界面,也就是说能为我们节省大量的时间。我们还能够非常直观地看出各个界面之间的关系,改动起来也非常方便。将来假设遇到须要作改动的地方。我们仅仅须...

数量线程SM,SP和GRID,BLOCK,THREAD之间的对应关系是什么?

最近应用开发的过程中出现了一个小问题,顺便记录一下原因和方法--数量线程     SM,SP是硬件构结          GRID,BLOCK,THREAD是软件念概                    从硬件度角讲,一个GPU由多个SM构成(当然还有其他部份),一个SM含包有多个SP(以及还有寄存器资源,shared memory资源,L1cache,...

iOS开发(Swift):创建UINavigationView的三种方法

UINavigationController是iOS开发中很常用的一种组件,由于种种原因许多人喜欢从代码创建视图控件,包括UINavigationController,但是有时候我们的屏幕控件太多,一方面使用storyboard可以方便设计,但是另一方面又需要用代码创建UINavigationController来灵活控制程序运行,下面将分别介绍代码,IB...

iOS开发——实时监控网速(仅作参考,发现一点问题)

  开发中用到获取网速的地方,应该就两种:   1、下载速度,这种可以直接在接受数据的地方统计计算。这个就不讲了。  2、获取手机网卡的数据,可以监控网卡的进出流量,下面就是。 #import "ViewController.h" #include <ifaddrs.h> #include <arpa/inet.h> #inclu...

iOS开发UI篇—Quartz2D简单使用(三)

iOS开发UI篇—Quartz2D简单使用(三) 一、通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联。 界面搭建,如图: 代码示例: YYViewController.m文件 1 // 2 // YYViewController.m 3...

ios开发网络学习十二:NSURLSession实现文件上传

#import "ViewController.h" //----WebKitFormBoundaryvMI3CAV0sGUtL8tr #define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx" #define KNewLine [@" " dataUsingEncoding:NSUTF8St...