- 写在前面: 翻翻各个iOS大牛的博客,或者在他们回答新手如何学习iOS开发时,"多看,一定要看苹果官方文档"这句话100%会出现."苹果人家是权威,多少博客都是翻译一遍罢了""不要啃人家嚼过的甘蔗".理都懂,然并卵.就结合自己情况来说,之前也看的不多原因有三:
- 1.中文看着多舒服,人忙忙的,问题解决就ok,想那多干啥
- 2.卧槽,密密麻麻这是啥,看两行吓得我电脑都关上了
- 3.问问自己的定位,你是不是一位合格并且有上进心的开发者?
其实对于大多数开发者来说,入了门之后,耳濡目染的都会写,认识些英文,所以其实还是一个懒,这句话也在说自己. 时光恍恍惚惚时间就这么没了,maybe失去些东西会让人突然安静下来.学习iOS一直自己做笔记,翻了翻自己的笔记,有些概念模模糊糊模棱两可,觉得是时候总结一波了.不想做咸鱼的我也就在这时候静下心来,看了一晚上苹果官网文档,对,是一晚上.不会的单词右击Look up, 复杂些的google.很恶心自己英文下降很多,但是观后感是:卧槽,这玩意才是武功秘籍好伐, 不管是guide还是一些api说明,实例code,绝逼权威,个人也觉得不会比一些中博客"翻译"过来的难理解. 一晚上,"soga...原来是这样!""这个这么理解才对""妈蛋,吃了这么久的二手甘蔗",是我整个心理活动.
当然夸张了, 只是觉得一是静下心来认真那种感觉很难得,二是官方文档真的很好.
这个集我想着自己尽量多的总结下官方文档的原文内容(不会大段落的翻译),带着自己(如果能帮到你就更好啦), 咱们去吃一手货!!
英文全部来自官方文档iOS9.1Document ,如果有错误,可能是复制或者打字错误, 开局了:
- Blocks Can Capture Values from the Enclosing Scope
(先别急着翻译,看下下面的这两个方法,猜下输出先.)
As well as containing executable code, a block also has the ability to capture state from its enclosing scope.
If you declare a block literal from within a method, for example, it’s possible to capture any of the values accessible within the scope of that method, like this:
- (void)testMethod {
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
testBlock();
}
In this example, anInteger is declared outside of the block, but the value is captured when the block is defined.
Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked, like this:
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
the value captured by the block is unaffected. This means that the log output would still show:
Integer is: 42 //输出是42```
It also means that the block cannot change the value of the original variable, or even the captured value (it’s captured as a const variable).
```objc
这里来总结文档意思: 不仅可以包含可执行代码一样,block能力超群,可以从封闭范围内获取值.
其实道理很简单,答案应该有2种: 42 ,84
42是觉得,可以的,不过这里是值传递
84觉得,外面修改了,我里面也用了,有可能吧.
随后文档给了解释: 除非你特殊定义,不然这个局部变量存在Block中后,后面你修改,它内部value是不影响的.
就像const来修饰一个变量,让它只读!
问题来了,那么怎样叫特殊定义,怎样可以修改? 来接下来就有解释了.
- Use __block Variables to Share Storage(这个标题自己翻译下)
If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration. This means that the variable lives in storage that is shared between the lexical scope of the original variable and any blocks declared within that scope.
As an example, you might rewrite the previous example like this:
__block int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
Because anInteger is declared as a __block variable, its storage is shared with the block declaration. This means that the log output would now show:
Integer is: 84 //这里输出就成84了
也就是说,用__block修饰变量,外部修改了这个变量,那么block里用得时候,就得注意了,值就变了.
用歪果仁的原文就是,Because anInteger is declared as a __block variable,
its storage is shared with the block declaration,分享给了你,这思维咋翻译嘛....
也就可以理解为,指针传递,带了__block这个修饰变量,外面修改,里面也会改
It also means that the block can modify the original value, like this:
(在看看这个:)
__block int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
anInteger = 100;
};
testBlock();
NSLog(@"Value of original variable is now: %i", anInteger);
This time, the output would show:
输出分别是:
Integer is: 42
Value of original variable is now: 100
- 也就意味者,外部修改变量,会影响block调用时它的值,同时block内部也可以修改,有执行顺序,猜猜那么下段怎么输出.
- (void)text {
__block int a = 10;
void(^block)() = ^void() {
a = 20; //先修改a
NSLog(@"a = %d",a);
};
block();
NSLog(@" new a = %d",a);
}
//没错,内部是按顺序执行的, a = 20 ,new a = 20
- 我也很疑惑,为什么加上_ block就可以了,是不是变量作用域的问题. 那么我就不加 _block,而是把a修饰成全局的试试? 加上static是什么效果? 自己去试试吧,下面是结果.
int a = 10;
- (void)text {
void(^block)() = ^void() {
a = 30;
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
/* 输出a = 30; new a = 30; 所以执行顺序就明白了:
先到a = 20; 然后进block
*/
--------------------------------------------
- (void)text2 {
static int a = 5;
void(^block)() = ^void() {
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
/* 输出a = 20; new a = 20; 所以执行顺序就明白了:
先到a = 20; 然后进block
*/
------------------------------
- (void)text3 {
static int a = 5;
void(^block)() = ^void() {
a = 30;
NSLog(@"%d",a);
};
a = 20;
block();
NSLog(@" new a = %d",a);
//输出 a = 30; new a = 30;
}
所以苹果这里说__block的意义在于,1. 在一个函数中,它不仅可以保存代码块
更是可以跳出那个{},获取外面的值 2.加上__block后,更是在block块儿内获取外面值得时候,先修改,再存入,
同时block内可以修改这个变量值,这里思想就不会禁锢在变量的作用域上.而是说Block的特性
所以不纠结其他的,总结block下就是两种传递:
1.值传递
2.指针传递. 为啥这么叫,用clang再编译下,然后查找对应传递,就会明白啦!