1

問題 : nil に設定された後、静的オブジェクトで dealloc メソッドが呼び出される順序で奇妙な動作が見られます。

問題を説明するために、2 つのメソッドを持つ BBSampleClass というクラス名を使用しました。

interface BBSampleClass : NSObject
+ (BBDummyObject*)getInstance; 
+ (void)cleanUp;
@end


static BBSampleClass *sInstance = nil;
@implementation BBSampleClass

+ (void)initialize
{
    sInstance = [[BBDummyObject alloc] init];
}

+ (BBDummyObject*)getInstance
{
    return sInstance;
}

+ (void)cleanUp
{
    sInstance = nil;
}

- (void)dealloc
{
    NSLog(@"BBSampleClass Object Dealloc");
}

@end

私のアプリケーションのある時点で、 BBSampleClass でクラス メソッド cleanUp を呼び出す(静的インスタンス変数sInstancenilに設定します)、他のステートメントを実行する直前にその dealloc が呼び出されることが予想されます。これは、その時点で他のオブジェクトが sInstance を所有していないためです。 .

つまり、これら2つのステートメントを実行します

[BBSampleClass cleanUp]
NSLog(@"After Cleanup");

コンソールに次のように出力する必要があります。これは正しいです。

**2013-01-11 14:14:32.280 BBSampleCode[7781:c07] BBSampleClass Object Dealloc

2013-01-11 14:14:32.280 BBSampleCode[7781:c07] クリーンアップ後**

ただし、このようにgetInstanceクラス メソッドを介して BBSampleClass のオブジェクトを取得しようとすると、

[BBSampleClass getInstance];//do something with object 
[BBSampleClass cleanUp];  
NSLog(@"After Cleanup");

NSLog ステートメントの実行順序が逆になります。つまり、ステートメントNSLog(@"After Cleanup")の実行後に BBSampleClass の静的オブジェクトの割り当てが解除されますが、これは誤りです。

 **2013-01-11 14:15:43.940 BBWebView[7811:c07] After Cleanup
2013-01-11 14:15:43.940 BBWebView[7811:c07] BBSampleClass Object Dealloc**

編集:解決策

[BBSampleClass getInstance] を @autoreleasepool { } ブロックに移動すると、問題が解決します。

4

2 に答える 2

2

initialize他のメッセージの前にクラスに送信されるためsTop、オブジェクトへの強い参照から始めます。

シナリオ #1:

[BBDummyObject cleanUp]を設定しますsTop = nil。オブジェクトへの最後の強い参照はなくなり、オブジェクトはすぐに割り当て解除されます。

したがって、「Dummy Dealloc」は「After Cleanup」の前に出力されます。

シナリオ #2:

Clang ARC ドキュメントの3.2.3 Unretained return valuesで説明されているように、この[BBDummyObject getInstance]メソッドは返されたオブジェクトsTopを保持し、自動解放プールに追加します。

[BBDummyObject cleanUp]を設定しますsTop = nil。これにより、オブジェクトへの強い参照が破棄さsTopれ、保持カウントが減少します。ただし、保持カウントはまだ正であるため、この時点ではオブジェクトは破棄されません。

次に、「クリーンアップ後」を出力します。

プログラムが現在の のスコープを離れると@autoreleasepool { }、自動解放プール内のすべてのオブジェクトがreleaseメッセージを受け取ります。オブジェクトの保持カウントがゼロになり、オブジェクトが解放されます。

したがって、「Dummy Dealloc」が印刷されるようになりました。

簡単な説明は次のとおり[BBDummyObject getInstance]です。現在の自動解放プールが破棄されると自動的に破棄される強い参照を作成します。したがって [BBDummyObject cleanUp]、オブジェクトをすぐに破棄せず、「Dummy Dealloc」の前に「After Cleanup」が出力されます。


getInstanceARC 命名規則により、保持されない戻り値を返します。メソッドの名前を に変更するcopyInstanceと、自動解放プールに追加されない (+1) 保持値が返されます。例えば:

BBDummyObject *obj = [BBDummyObject copyInstance]; // retain count of object is increased.
// do something with obj ...
obj = nil; // retain count is decreased immediately.
[BBDummyObject cleanUp]; // should dealloc object immediately.
于 2013-01-11T22:11:41.707 に答える
1
Scenario #1

[BBDummyObject cleanUp];
NSLog(@"After Cleanup");

Output #1

 Dummy Dealloc
 After Cleanup

これはいくぶんまっすぐです:

に設定している cleanUp を呼び出しましたnil。どの結果を呼び出すか。deallocその後、あなたNSLogはうまくいきました。

于 2013-01-11T21:50:33.027 に答える