这些例子有什么不同?我无法弄清楚为什么它们不同并提供不同的结果。我看到,块中的代码是在某个时候在主线程中运行,第一个代码提供的结果是foo或bar,并且不确定原因和时间。
NSString *myString = @"foo";
dispatch_async (dispatch_get_main_queue(), ^{
NSLog (@"%@", myString);
});
myString = @"bar";
第二
NSMutableString *myString = [NSMutableString stringWithString:@"foo"];
dispatch_async (dispatch_get_main_queue(), ^{
NSLog (@"%@", myString);
});
[myString setString:@"bar"];
答案 0 :(得分:4)
这是非常微妙的(即,最好是构造代码以避免回答这个问题:))
在第一个示例中,块捕获指向文字常量NSString的指针的const副本。然后更新原始指针以指向新字符串。该块应该在主线程之后的某个任意点打印“foo”。
在第二个示例中,块捕获指向可变NSString的指针的const副本。然后更新可变NSString以具有不同的内容。如果代码在非主线程/队列上运行,则块可能会打印“foo”,可能会打印“bar”,或者由于在字符串更改时打印字符串而崩溃。如果块在主线程/队列上,那么它将打印“bar”。
答案 1 :(得分:3)
区别在于:
在第一种情况下,您有两个不同的对象@"foo"
和@"bar"
。 myString
首先指向@"foo"
,然后将其更改为指向@"bar"
。
在第二种情况下,您有一个对象NSMutableString
。 myString
始终指向该对象。但是,NSMutableString
的内容从"foo"
更改为"bar"
。
When you create a block, it captures the values of any local variables that it uses from the enclosing scope.因此,在第一种情况下,该块在指向myString
时会捕获@"foo"
。稍后更改以使其指向@"bar"
不会影响块中捕获的副本。
在第二种情况下,块捕获myString
的值。但是,它不捕获myString
指向的对象的状态。因此,您可以更改对象的内容,并且块在运行时将看到新内容。
顺便说一句,这与dispatch_async
,GCD或多线程无关。如果直接并同步运行块,您会看到相同的效果。
NSString *myString = @"foo";
void (^myBlock)(void) = ^{
NSLog (@"%@", myString);
};
myBlock(); // prints "foo"
myString = @"bar";
myBlock(); // prints "foo"
NSMutableString *myString = [NSMutableString stringWithString:@"foo"];
void (^myBlock)(void) = ^{
NSLog (@"%@", myString);
};
myBlock(); // prints "foo"
[myString setString:@"bar"];
myBlock(); // prints "bar"
答案 2 :(得分:2)
以下是您首次创建块并调用dispatch_async
时的外观:
--NSString-------
| "Foo" |
-----------------
^ ^
| |
myString GCD Block
以下是它对函数结束的看法。您将myString
分配给一个新的NSString实例,该实例与该块捕获的实例不同:
--NSString------- --NSString-------
| "Foo" | | "Bar" |
----------------- -----------------
^ ^
| |
GCD Block myString
在这种情况下,无论块何时执行,块都将始终打印“Foo”。
第二个例子同样开始:
--NSMutableString----
| "Foo" |
---------------------
^ ^
| |
myString GCD Block
除非您正在修改块捕获的相同NSMutableString实例:
--NSMutableString----
| "Bar" |
---------------------
^ ^
| |
myString GCD Block
该块可以打印“Foo”或“Bar”,具体取决于它执行的时间。如果块打印“Bar”,则表示在修改NSMutableString实例后执行了块。