对OC中的闭包(Block)理解

时间:2022-04-20 22:45:39

前文:这些是我在网上学习时总结的, 和自己写得代码, 总结那个有可能会总结的不规范, 希望大家看到多给提议, 有的时候也是没来的写自己总结的话, 说明我还在吸收, 在想怎么用简单的语句说清楚, 欢迎大家一起讨论…
一. 定义
引用伯乐的一句话, 就是匿名函数, 也就是在函数中可以包含着函数.就是在函数中可以定义匿名函数然后在函数中调用.
伯乐对OC中闭包的定义:
二.分类

 1.无参无返回值
void(^block1)(void) = ^void(void) {
NSLog(@"无参无返回值");
};
// 调用
block1();

输出:
2016-01-15 00:26:47.350 Block[52261:1826337] 无参无返回值

// 2.有参无返回值
void (^block2)(NSString *, NSMutableArray *) = ^void(NSString *string, NSMutableArray *array) {
[array addObject:string];
NSLog(@"%@", array);
};
// 参数传入
block2(@"abc", [NSMutableArray array]);

输出:
2016-01-15 00:33:47.110 Block[52641:1832232] (
abc
)

// 3.无参有返回值
NSInteger (^block3)(void) = ^(void) {
return 100l;
};
NSLog(@"%ld", block3());

输出:
2016-01-15 00:36:10.767 Block[52777:1833844] 100

// 4.有参有返回值
NSMutableDictionary *(^block4)(NSString *, NSArray *) = ^(NSString *string, NSArray *array) {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:array forKey:string];
return dic;
};
NSLog(@"%@", block4(@"alphabet", @[@"a", @"b"]));

输出:
2016-01-15 00:41:24.466 Block[53058:1837287] {
alphabet = (
a,
b
);
}
三.block和变量之间的联系
block可以对全局变量进行访问和修改, 但是局部变量只能访问, 不能修改 如果一定要修改则需要在局部变量钱加上__block进行

NSInteger global = 200l;// 有一个全局变量
// block与变量
__block NSInteger figure = 100l;
void (^block)(void) = ^(void) {
NSLog(@"%ld", figure);
};
block();

输出:
2016-01-15 00:48:23.344 Block[53422:1843154] 100
四.BLOCK与重定义

typedef void(^BLOCK)(id); // 重定义
// block的重定义使用
BLOCK blockPrint = ^(id object) {
NSLog(@"%@", object);
};
blockPrint(@[@"1", @"2"]);

输出
2016-01-15 00:54:15.053 Block[53732:1848630] (
1,
2
)
五 :使用Block进行排序

// 使用Block进行排序
// 不可变数组
NSArray *array = @[@"a", @"z", @"f"];
NSComparator blockCMP = ^(id obj1, id obj2) {
// return [obj1 compare:obj2]; // 升序
return -[obj1 compare:obj2]; // 降序
};
NSArray *newArr = [array sortedArrayUsingComparator:blockCMP];
blockPrint(newArr);
// 直接方法
NSArray *nnArr = [array sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2];
}];
blockPrint(nnArr);
// 可变数组
NSMutableArray *mArr = [NSMutableArray arrayWithArray:array];
[mArr sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2];
}];
blockPrint(mArr);

输出:
2016-01-15 01:06:59.725 Block[54462:1857348] (
z,
f,
a
)
2016-01-15 01:06:59.725 Block[54462:1857348] (
a,
f,
z
)
2016-01-15 01:06:59.725 Block[54462:1857348] (
a,
z,
f
)
注意补充:
给block进行赋值的方式有两种, 一种是声明的时候直接赋值, 在一个就是先声明再赋值
六.在局部变量中对比可变对象与不可变对象在block中的引用
用来证明上面提到过的
“block可以对全局变量进行访问和修改, 但是局部变量只能访问, 不能修改 如果一定要修改则需要在局部变量钱加上__block进行

void blockTest1();
{
// 定义两个变量一个是可变的一个是不可变的
NSString *str1 = @"str1";
NSMutableString *str2 = [NSMutableString stringWithFormat:@"str2"];
// 初始值
NSLog(@"两个字符串的初始值和初始地址");
NSLog(@"str1 = %@, str1_p = %p", str1, str1);
NSLog(@"str2 = %@, str2_p = %p", str2, str2);
//定义block在block中输出两个变量的值和参数
void(^myBLock)() = ^() {
NSLog(@"****************");
NSLog(@"在block块中输出局部变量的可变和不可变变量");
NSLog(@"str1 = %@, str1 = %p", str1, str1);
NSLog(@"str2 = %@, str2_p = %p", str2, str2);
};
// 修改前赋值
str1 = @"str1_update";
[str2 appendString:@"_update"];
NSLog(@"****************");
NSLog(@"输出修改后的值和地址");
NSLog(@"str1 = %@, str1 = %p", str1, str1);
NSLog(@"str2 = %@, str2_p = %p", str2, str2);
// 调用block
myBLock();
NSLog(@"****************");
NSLog(@"调用block后的值和地址");
NSLog(@"str1 = %@, str1 = %p", str1, str1);
NSLog(@"str2 = %@, str2_p = %p", str2, str2);
}

结果:
2016-01-15 01:12:55.547 Interview Questions One_OC[54782:1862892] 两个字符串的初始值和初始地址
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str1 = str1, str1_p = 0x1000052b0
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str2 = str2, str2_p = 0x100206f80
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] 输出修改后的值和地址
2016-01-15 01:12:55.549 Interview Questions One_OC[54782:1862892] str1 = str1_update, str1 = 0x1000053b0
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] 在block块中输出局部变量的可变和不可变变量
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str1 = str1, str1 = 0x1000052b0
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] ******
2016-01-15 01:12:55.550 Interview Questions One_OC[54782:1862892] 调用block后的值和地址
2016-01-15 01:12:55.551 Interview Questions One_OC[54782:1862892] str1 = str1_update, str1 = 0x1000053b0
2016-01-15 01:12:55.551 Interview Questions One_OC[54782:1862892] str2 = str2_update, str2_p = 0x100206f80
结论:
从不可变对象来看, 无论是值还是地址都是最刚开始的,
但是从可变对象来看, 值是修改过的值, 但是地址还是最刚开始的地址.
七.成员变量在block中的使用

#import "BlockTest.h"
BlockTest *test = [[BlockTest alloc] init];
[test test];
@interface BlockTest : NSObject
{
__block NSString *hasBlock;
NSString *noBlock;
}

- (void)test;
- (void)test {
// 分别给两个成员变量赋初始值
hasBlock = @"ludashi";
noBlock = @"liudashi";
NSLog(@"hasBlock = %<a href = 'http://www.jobbole.com/members/uz441800'>@,</a> hasBlock_p = %p", hasBlock, hasBlock);
NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
// 定义Block
void(^myBlock)() = ^() {
// 修改__block的成员变量的值
hasBlock = @"liudashi_update";
NSLog(@"block中输出的内容");
NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
};
// 改变noBlock的值
NSLog(@"更新后的值");
NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);
// 调用block
myBlock();
NSLog(@"调用block后的值");
NSLog(@"hasBlock = %<a href = 'http://www.jobble.com/member/ua441800'>@, </a> hasBlock_p = %p", hasBlock, hasBlock);
NSLog(@"noBlock = %@, noBlock_p = %p", noBlock, noBlock);

}

输出:
2016-01-15 01:21:41.587 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobbole.com/members/uz441800‘>@, hasBlock_p = 0x100004270
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] 更新后的值
2016-01-15 01:21:41.588 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x100004270
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] block中输出的内容
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x1000042f0
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290
2016-01-15 01:21:41.589 Interview Questions One_OC[55254:1870362] 调用block后的值
2016-01-15 01:21:41.590 Interview Questions One_OC[55254:1870362] hasBlock = http://www.jobble.com/member/ua441800‘>@, hasBlock_p = 0x1000042f0
2016-01-15 01:21:41.590 Interview Questions One_OC[55254:1870362] noBlock = liudashi, noBlock_p = 0x100004290