1

これらの例の違いは何ですか? なぜそれらが異なり、異なる結果を提供するのかわかりません。ご覧のとおり、ブロック内のコードはいつかメインスレッドで実行され、最初のコードによって提供される結果は foo または bar のいずれかであり、その理由とタイミングは不明です。

NSString *myString = @"foo";
dispatch_async (dispatch_get_main_queue(), ^{
    NSLog (@"%@", myString); 
});
myString = @"bar";

2番:

NSMutableString *myString = [NSMutableString stringWithString:@"foo"]; 
dispatch_async (dispatch_get_main_queue(), ^{
    NSLog (@"%@", myString); 
});
[myString setString:@"bar"];
4

3 に答える 3

4

これはかなり微妙です (つまり、この質問に答える必要がないようにコードを構造化するのがおそらく最善でしょう :) )

最初の例では、ブロックはリテラル定数 NSString へのポインターの const コピーをキャプチャします。次に、元のポインターが更新されて、新しい文字列を指すようになります。ブロックは、後でメインスレッドから任意の時点で「foo」を出力する必要があります。

2 番目の例では、ブロックは変更可能な NSString へのポインターの const コピーをキャプチャします。次に、変更可能な NSString が更新されて、異なる内容になります。コードが非メイン スレッド/キューで実行されている場合、ブロックは "foo" を出力したり、"bar" を出力したり、変更中の文字列を出力するためにクラッシュしたりする可能性があります。ブロックがメインスレッド/キューにある場合、「バー」が出力されます。

于 2013-01-01T20:47:11.040 に答える
3

違いは次のとおりです。

  • 最初のケースでは、2 つの異なるオブジェクト と が@"foo"あり@"bar"ます。myString最初に を指し@"foo"、次に を指すように変更します@"bar"

  • 2 番目のケースでは、1 つのオブジェクトNSMutableString. myString常にそのオブジェクトを指しています。ただし、その内容はからにNSMutableString変わります。"foo""bar"

ブロックを作成すると、それが使用するすべてのローカル変数の値が含まれているスコープから取得されます。 したがって、最初のケースでは、ブロックmyStringは を指していたときにキャプチャし@"foo"ます。それを指すようにするための後の変更@"bar"は、ブロック内のキャプチャされたコピーには影響しません。

2 番目のケースでは、ブロックは の値を取得します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"
于 2013-01-01T20:50:20.280 に答える
2

最初にブロックを作成して を呼び出すと、次のようになりますdispatch_async

    --NSString-------
    |     "Foo"     |
    -----------------
      ^      ^
      |      |
myString    GCD Block

関数の最後は次のようになります。myStringブロックによってキャプチャされたものとは異なる、まったく新しい NSString インスタンスに割り当てています。

    --NSString-------  --NSString-------
    |     "Foo"     |  |     "Bar"     |
    -----------------  -----------------
             ^             ^
             |             |
       GCD Block          myString

この場合、ブロックがいつ実行されるかに関係なく、ブロックは常に「Foo」を出力します。

2 番目の例も同様に始まります。

    --NSMutableString----
    |     "Foo"         |
    ---------------------
      ^      ^
      |      |
myString    GCD Block

ブロックによってキャプチャされた同じ NSMutableString インスタンスを変更している場合を除きます。

    --NSMutableString----
    |     "Bar"         |
    ---------------------
      ^      ^
      |      |
myString    GCD Block

ブロックは、いつ実行されるかに応じて、「Foo」または「Bar」のいずれかを出力できます。ブロックに「Bar」と表示されている場合は、NSMutableString インスタンスを変更した後にブロックが実行されたことを意味します。

于 2013-01-01T21:05:11.560 に答える