28

少し頑固なところもありますが、弱い参照と強い参照をよく理解したいので、もう一度お願いします。

このことを考慮:

__weak NSString* mySecondPointer = myText;   
NSLog(@"myText: %@", myText);

結果はmyText: (null)非常に明白です-弱い参照は割り当ての直後にnullに設定されます。これは、指定されたオブジェクトへの強い参照がないためです。

しかし、この場合:

__strong NSString* strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d"]; 
// weak pointer points to the same object as strongPtr
__weak NSString* weakPtr = strongPtr;
if(strongPtr == weakPtr) 
     NSLog(@"They are pointing to the same obj");        
NSLog(@"StrongPtr: %@", strongPtr);
NSLog(@"weakPtr: %@", weakPtr);

NSLog(@"Setting myText to different obj or nil");

// after line below, there is no strong referecene to the created object:
strongPtr = [[NSString alloc] initWithString:@"abc"];  // or myText=nil;

if(strongPtr == weakPtr) 
     NSLog(@"Are the same");
else
     NSLog(@"Are NOT the same");
NSLog(@"StrongPtr: %@", strongPtr);
// Why weak pointer does not point to nul
NSLog(@"weakPtr: %@", weakPtr);

出力:

2013-03-07 09:20:24.141 XMLTest[20048:207] They are pointing to the same obj
2013-03-07 09:20:24.142 XMLTest[20048:207] StrongPtr: mYTeSTteXt 3
2013-03-07 09:20:24.142 XMLTest[20048:207] weakPtr: mYTeSTteXt 3
2013-03-07 09:20:24.143 XMLTest[20048:207] Setting myText to different obj or nil
2013-03-07 09:20:24.143 XMLTest[20048:207] Are NOT the same
2013-03-07 09:20:24.144 XMLTest[20048:207] StrongPtr: abc
2013-03-07 09:20:24.144 XMLTest[20048:207] weakPtr: mYTeSTteXt 3   // <== ??

私の質問:

弱いポインターの値が nil に変更されないのはなぜですかstrongPtr = [[NSString alloc] initWithString:@"abc"];(最初に作成されたオブジェクトは、強い参照がないにもかかわらず、メモリ内にまだ存在するのはなぜですか? -- または、存在する可能性がありますか?)


私はそれを試しました:(しかし、コメントを追加するには適していないと思います)。@autorealesepool で strongPtr を作成するコードを含めました。それが正しい解決策かどうかはわかりませんが、うまくいきます...

 __strong NSString* strongPtr;
    __weak NSString* weakPtr;
    @autoreleasepool {


        strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d", 3];

        // weak pointer point to object create above (there is still strong ref to this obj)
        weakPtr = strongPtr;
        if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj");        

        NSLog(@"StrongPtr: %@", strongPtr);
        NSLog(@"weakPtr: %@", weakPtr);

        NSLog(@"Setting myText to different obj or nil");   

    // after line below, there is no strong referecene to the created object:
     strongPtr = [[NSString alloc] initWithString:@"abc"];  


    }

    if(strongPtr == weakPtr) 
        NSLog(@"Are the same");
    else
        NSLog(@"Are NOT the same");
    NSLog(@"StrongPtr: %@", strongPtr);
    // Why weak pointer does not point to nul
    NSLog(@"weakPtr: %@", weakPtr);

出力:

2013-03-07 09:58:14.601 XMLTest[20237:207] They are pointing to the same obj
2013-03-07 09:58:14.605 XMLTest[20237:207] StrongPtr: mYTeSTteXt 3
2013-03-07 09:58:14.605 XMLTest[20237:207] weakPtr: mYTeSTteXt 3
2013-03-07 09:58:14.606 XMLTest[20237:207] Setting myText to different obj or nil
2013-03-07 09:58:14.607 XMLTest[20237:207] Are NOT the same
2013-03-07 09:58:14.607 XMLTest[20237:207] StrongPtr: abc
2013-03-07 09:58:14.608 XMLTest[20237:207] weakPtr: (null)
4

4 に答える 4

17

アセンブリ コードから、アクセスによって呼び出しがweakPtr生成されることがわかりobjc_loadWeakます。

Clang documentationによるとobjc_loadWeak、オブジェクトを保持および自動解放し、次と同等です

id objc_loadWeak(id *object) {
  return objc_autorelease(objc_loadWeakRetained(object));
}

これは(うまくいけば)両方の理由を説明します

if(strongPtr == weakPtr) ...

NSLog(@"weakPtr: %@", weakPtr);

追加の自動解放参照を作成します。

これは特別なNSString問題ではありません。カスタム (プレーン) クラスで同じ動作を再現できました。

于 2013-03-07T09:21:11.293 に答える
3

まず、 で弱い参照やその他のメモリ管理動作を試してはいけませんNSString。そのクラスには魔法が多すぎます。弱い参照が で機能しないというわけではありませんがNSString、動作が予想よりも少しトリッキーであり、誤った結論に簡単につながるだけです。次の以前の質問を参照してください。

コード例を自動解放プールでラップし、後で弱い文字列ポインターをログに記録すると、nil実際にそうなります。オブジェクトへの最後の強い参照を失う正確なNSString瞬間に弱い参照がクリアされるという保証はありません。または、そうかもしれませんが、この例で示唆されているように (そして Martin の回答でうまく説明されているように)、実行中の自動解放プールのために、最後の強い参照がいつ消えるかを正確に判断するのは困難です。

于 2013-03-07T08:46:43.650 に答える
1

あなたがするとき

strongPtr = [[NSString alloc] initWithString:@"abc"]

strongPtr は新しく割り当てられたオブジェクトを指していますが、それが指していた以前のオブジェクトも割り当てが解除されなかったため、弱いポインターは引き続き有効なアドレスを指しています。

ところで。オブジェクトからメモリアドレスを出力できます

NSLog(@"%@", [NSString stringWithFormat:@"%p", theObject])

于 2013-03-07T08:46:04.923 に答える