10

重複の可能性:
弱い NSString プロパティが iOS でリリースされないのはなぜですか?

私は Objective C の初心者で、自分では答えられない質問がいくつかあります。__weak 変数をテストするためのコード ブロックがあります (もちろん、ARC を使用しています)。

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
myString = nil; //<-- release the NSString object
NSLog(@"string: %@", weakString);

weakString は弱い変数であるため、上記のコードの出力は期待どおりです。

2013-01-02 11:42:27.481 ConsoleApp[836:303] string: (null)

しかし、コードを次のように変更すると、次のようになります。

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
NSLog(@"Before: %@", weakString); //<--- output to see if the __weak variable really works.
myString = nil;
NSLog(@"After: %@", weakString);

出力は私が期待したものとはまったく異なります:

2013-01-02 11:46:03.790 ConsoleApp[863:303] Before: John
2013-01-02 11:46:03.792 ConsoleApp[863:303] After: John

後者の NSLog の出力は、"John" ではなく (nil) である必要があります。多くのドキュメントを検索しようとしましたが、この場合の答えが見つかりませんでした。誰かが合理的な説明をすることができますか? 前もって感謝します。

4

2 に答える 2

7

このNSLog関数は、渡されたNSStringを自動解放プールに保持しています。したがって、ゼロ化弱変数は、自動解放プールが空になるまでゼロ化されません。例えば:

__weak NSString* weakString = nil;

@autoreleasepool {
    NSString* myString = [[NSString alloc] initWithFormat:@"Foo"]; // Retain count 1
    weakString = myString;         // Retain count 1
    NSLog(@"A: %@", weakString);   // Retain count 2
    NSLog(@"B: %@", weakString);   // Retain count 3
    myString = nil;                // Retain count 2
    NSLog(@"C: %@", weakString);   // Retain count 3

    NSAssert(weakString != nil, @"weakString is kept alive by the autorelease pool");
} 

// retain count 0
NSAssert(weakString == nil, @"Autorelease pool has drained.");

NSLogが文字列を自動解放プールに入れるのはなぜですか?これが実装の詳細です。

デバッガーまたはInstrumentsを使用して、NSStringインスタンスの保持カウントを追跡できます。正確な保持数は重要ではありませんが、舞台裏で何が起こっているかについてはある程度の光を当てています。重要なのは、自動解放プールが空になると、NSStringインスタンスの割り当てが解除されることです。

于 2013-01-02T07:12:23.410 に答える
0

実装の詳細に過ぎないと思います。あなたの弱い変数はクリアされていますが、すぐにではありません。たとえば、これは期待どおりに機能します。

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
@autoreleasepool {
    NSLog(@"Before: %@", weakString);
    myString = nil;
}
NSLog(@"After: %@", weakString); // nil
于 2013-01-02T07:12:53.317 に答える