5

GCD を使用したマルチスレッドのスキルを習得しているときに、いくつかの質問に出くわしました。次のメソッドがあるとします。

    - (void)method {
    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    NSLog(@"%@", string); //is it safe?
    });
}

ブロックの実行前に文字列を保持する必要があると思うので、これが正しいかどうか疑問に思っています。実際、イベントループが終了し、ブロックでstring使用する前に自動解放メッセージを送信するのではないかと心配してstringいます。それはプログラムをクラッシュさせるでしょう。

私は正しいですか?保持および解放メッセージを送信する必要stringがありますか、これは正しい実装ですか? 前もって感謝します!

4

2 に答える 2

5

ブロックの実行前に文字列を保持する必要があると思うので、これが正しいかどうか疑問に思っています。実際、ブロックで文字列を使用する前に、イベントループが終了し、文字列に自動解放メッセージを送信するのではないかと心配しています。

恐れる必要はありません。ブロックは、ブロック内で使用されるすべてのオブジェクト変数を
自動的に s するという点で、周囲のメソッド/関数のスコープをキャプチャします。オブジェクトの寿命に大きく影響する可能性があるため、ブロック内でretain使用する場合は注意してください!self

このルールには例外が 1 つあります。それは、次のように宣言された変数です。

__block SomeObjectPointerType variableName

アップデート

この回答には新しいコメントがあるため、ARCの導入により状況が少し変わったことをおそらく追加する必要があります。

ARC では、すべてのオブジェクト変数のデフォルトは__strongであり、これは でマークされた変数にも当てはまり__blockます。ブロック内の変数の強力なキャプチャを避けたい場合は、ローカル変数を定義する必要があります__weak

更新終了

ブロックについて詳しく知りたい場合は、bbum がWWDC 2010で iPhone のブロックの紹介とグランド セントラル ディスパッチという優れたセッションを行いました。

11:30 からは「ブロックの詳細」のコーナーが始まります。

于 2011-02-13T13:35:20.250 に答える
-5

懸念は; 自動解放オブジェクトが解放されるとき?

NSString *myString= [NSString stringWithFormat: @"%@", stringVariable];

myStringは、stringVariableが解放されるたびに、stringVariableに依存します。myStringはすぐに解放されます。

NSString *myString= [NSString stringWithString: @"stringVariable"];

実際には、myStringはメソッドの完了直後にリリースされる可能性があることが観察されています。

コードを変更してNSAutoReleasePoolを使用すると

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    // string will be released here
    [pool release];

    NSLog(@"%@", string); // it is not safe?
    });
}

自動解放オブジェクトは、それらが存在する自動解放プールが解放されたとき、またはオブジェクトが依存して解放されたときに解放されます。

スレッドでメソッドを使用している場合は、その中の自動解放プールを使用する必要があります。

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

        // lengthy operations ...
    [pool release];
}
于 2011-02-13T11:16:28.297 に答える