iOS block 基本用法总结
简书地址:http://www.jianshu.com/p/d89e19c08afb
一、block定义
- block定义:是OC中的一种数据类型,可以保存代码,传递参数等,被广泛的运用于iOS开发中。
- ^是block的特有标记
block的实现方法的代码实在{}之间
block的定义(如下示例代码):
//声明形式 返回值(^块名称)(参数类型 参数名,参数类型 参数名,...)
1.)不带参数的block
void(^noArgumentsBlock)() = ^{
NSLog(@"no Arguments");
};
2.)单个参数的block
void(^oneArgumentBlock)(int) = ^(int n){
NSLog(@"%d", n);
};
oneArgumentBlock(10); //传值
3.)带行参的block
int (^sumBlock)(int, int) = ^(int a,int b){
return a+b;
};
int sum = sumblock(1,2); //调用 有返回值
4.)typedef定义的block
typedef int(^SumBlock)(int,int);
SumBlock sumblock = ^(int a,int b){
//执行的方法
}
二、Block使用
- block作为参数在NSArray中的运用
/**
* 查找字母为B的元素所在位置
* enumerateObjectsUsingBlock与 for(... in ...)方法相比较,都是基于 NSFastEnumeration 实现的,在效率上基本一致,有时前者更快。
* 注意"enumerateObjectsUsingBlock" 修改局部变量时, 你需要声明局部变量为 __block 类型。
* 默认情况下,block外部的变量,在block中是只读的。
*/
NSArray *array = @[@"A",@"B",@"C",@"D",@"E"];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"数组的第%d个元素是%@", (int)idx, obj);
if ([obj isEqualToString:@"B"])
{
*stop = YES;
NSLog(@"字母为B的元素为第%d个", (int)idx);
}
}];
__block BOOL flag = NO;
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isEqualToString:@"B"])
{
*stop = YES;
flag = YES;//__block类型才能进行修改
}
}];
//值得注意的是 block是不允许修改外部变量的值,也就是不能修改栈中指针的内存地址,_block所起到的作用是将改变量的在栈中的内存放到了堆中。
2.block作为参数在NSDictionary中的运用
/**
* 查找Value为Bob所对应的key
* 遍历字典时 enumerateObjectsUsingBlock 效率高
* 注意"enumerateObjectsUsingBlock" 修改局部变量时, 你需要声明局部变量为 __block 类型。
* 默认情况下,block外部的变量,在block中是只读的。
*/
NSDictionary *dictionary =
@{
@"A" : @"Amy",
@"B" : @"Bob",
@"C" : @"Catch",
@"D" : @"Dany"
};
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([obj isEqualToString:@"Bob"])
{
*stop = YES;
NSLog(@"%@", key);
}
}];
3.block在传递参数中的运用
声明文件.h
#import <UIKit/UIKit.h>
typedef void(^NumInputBackBlock)(NSString *sure, NSString *text);
@interface NumberInputView : UIView
@property (nonatomic, copy) NumInputBackBlock numInputBackBlock;
@end
声明文件.m
//点击事件发送block传递参数
- (void)sure:(UIButton *)sender
{
_numInputBackBlock(@"sure",@"text");
}
实现文件.m
NumberInputView *numInput = [[NumberInputView alloc] init];
numInput.numInputBackBlock = ^(NSString *state, NSString *text){
NSLog(@"%@, %@", state, text);
};
4.block的注意事项
- 循环引用(retain cycle)
- 去除blockt提示的告警
修改(1):Capturing ‘keyBoard’ strongly in this block is likely to lead to a retain cycle
直接引用外部的变量,因为ARC的机制,会造成循环引用
修改(2):Assigning retained object to weak variable;object will be released after assignment
变量加上__weak修饰,变量在ARC中马上就会被释放,不会再block中执行。
修改(3):
这样就解决了!
提示:一般在block中使用self 要在外部的对self进行处理,防止retain cycle的出现。处理方法如下:
__weak __typeof(&*self)weakSelf = self;
__weak __typeof(self) weakSelf = self;
__weak XxxViewController *weakSelf = self;
__weak id weakSelf = self;
以上都可以!