OC之Block的使用

一.Block定义

1.1 定义

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

(2)^Block的特有标记

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

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

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

1.2示例代码

void(^demoBlock)() =^ {
   NSLog(@"demo");
};
int(^addBlock)(int, int) =^(int x, int y) {
   return x +y;
};

说明:
(1)(返回类型)(^块名称)(参数类型)=^(参数列表){代码实现};
(2)如果没有参数,等号后面参数列表的()可以省略


.Block使用

2.1 Block被当做参数直接传递

<span style="font-size:18px;">NSArray *array= @[@"张三",@"李四",@"王五",@"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL*stop) {
   NSLog(@"第 %d 项内容是 %@",(int)idx, obj);
   if ([@"王五"isEqualToString:obj]) {
        *stop = YES;
   }
}];</span>


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

2.2  对象传递进 Block 的方式

NSString *stopName =@"王五";
NSArray *array= @[@"张三",@"李四",@"王五",@"赵六"];
[array enumerateObjectsUsingBlock:^(idobj, NSUInteger idx,BOOL *stop) {
   NSLog(@"第 %d 项内容是 %@",(int)idx, obj);
   if ([stopName isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
   }
}];


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


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

<span style="font-size:18px;">intstopIndex = 1;
NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLog(@"第 %d 项内容是 %@", (int)idx, obj);
    if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
    }
}];</span>

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

<span style="font-size:18px;">BOOL flag = NO;
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
        flag = YES;      // 编译错误!!!
        }
}];</span>

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

<span style="font-size:18px;">__block BOOL flag = NO;
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
        flag = YES;      // 现在可以修改了!!!
        }
}];</span>


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


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

<span style="font-size:18px;">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));</span>


说明:
   (1) typedef是关键字用于定义类型,MyBlock是定义的Block类型
(2)areasum分别是MyBlock类型的两个Block变量
(3)尽管,typedef可以简化Block的定义但在实际开发中并不会频繁使用typedef关键字这是因为Block具有非常强的灵活性,尤其在以参数传递时,使用Block的目的就是为了立即使用


2.5 添加到数组
Block一种数据类型可以将Block当做比较特殊的对象

<span style="font-size:18px;">#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);</span>



2.6 Block循环引用问题

直接上代码:

@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被释放");
}
说明:

上面的代码出现的问题,循环引用的结果就是对象无法被释放!

(1)self对myBlocks的强引用

(2)sum对self的强引用

(3)对象被添加到数组中,会被数组强引用


问题解决:

局部变量默认都是强引用的,离开其所在的作用域之后就会被释放,使用__weak关键字,可以将局部变量声明为弱引用

	__weak DemoObj *weakSelf =self;


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

int(^sum)(int, int) = ^(int x, int y) {
    	return [weakSelf sum:x y:y];
	};


2.7 Block在iOS中使用场景

(1) 遍历数组或者字典
(2) 视图动画
(3) 排序
(4) 通知
(5) 错误处理

(6)多线程等等...



























  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值