web-dev-qa-db-ja.com

なぜ最初ではなく最後にsuper-deallocを呼び出さなければならないのですか?

正しい例:

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

間違った例:

- (void)dealloc {
    [super dealloc];
    [viewController release];
    [window release];
}

他のほとんどすべての場合、メソッドをオーバーライドするときは、最初にスーパーのメソッド実装を呼び出します。この場合、Appleは常に最後に[superdealloc]を呼び出します。なぜですか?

29
Thanks

その単なるガイドライン。 [super dealloc]の後に他の命令を呼び出すことができます。ただし、[super dealloc]を呼び出すと解放されるため、スーパークラスの変数にアクセスできなくなります。最後の行でスーパークラスを呼び出すことは常に安全です。

また、KVOおよび依存(トリガー)キーは、すでにリリースされているメンバー変数に依存している場合、副作用を引き起こす可能性があります。

54
cocoafan

IPhoneのプログラミングについては何も知りませんが、デストラクタを逆の順序で呼び出す必要があるのも同じ理由だと思います。スーパークラスを呼び出す前に、すべての「ゴミ」がクリーンアップされていることを確認する必要があります。逆にすると、物事が乱雑になる可能性があります。たとえば、デストラクタがスーパーデストラクタがすでに解放したメモリにアクセスする必要がある場合:

class X {
    private Map foo;

    function __construct() {
        foo = new Map();
    }

    function __destruct() {
        foo.free;
    }
}

class Y extends X {
    function __construct() {
        super.__construct();
        map.put("foo", 42);
    }

    function __destruct() {
        super.__destruct();
        if (map.containsKey("foo")) {    // boooooooooom!
            doSomething();
        }
    }
}

yourコードでは、「自分が何をしているのかがわかっている」ため、この問題が発生しない可能性がありますが、そのようなことをしない方が安全で全体的に優れた方法です。

12
n3rd

[スーパーdealloc]は、viewControllerやwindowへのポインタなど、オブジェクトが使用するメモリを解放します。変数を解放した後で変数を参照することは、せいぜい危険です。

この回答 を参照してください。

5
Terry Wilcox

[superdealloc]を最後にする必要がある実際の例を次に示します。そうしないとremoveFromRunLoopを呼び出すとクラッシュします。 NSOutputStreamのremoveFromRunLoop内で何が起こるかはわかりませんが、この場合は「self」にアクセスしているようです。

セットアップ:

[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

Dealloc:

- (void)dealloc {
    if (outputStream) {
        [outputStream close];
        [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                                forMode:NSDefaultRunLoopMode];
        [outputStream release];
        outputStream = nil;
    }
    delegate = nil;
    [super dealloc]; // must be last!
}
2
Simo Salminen

スーパークラスの変数が解放され、それらにアクセスできなくなるため、実質的に最後に[super dealloc]があります。

1つの例外は、テーブルビューデリゲートとして別のクラスを使用しているUITableViewControllerのサブクラスがある場合です。その場合、テーブルビューはテーブルビューデリゲートを参照しており、テーブルビューを最初に解放する必要があるため、[super dealloc]の後にテーブルビューデリゲートを解放する必要があります。

1
kareman

[最後の投稿へ]デリゲートを参照するtableViewは、自身のデリゲートを解放する責任がありませんか?設定時に保持され(リリースまたは自動リリースできるように)、それ自体が処理されると思いますか?

OPの質問については、構築している場合は常にスーパーを最初に呼び出し、破壊している場合はスーパーを最後に呼び出します。 「自分が欲しいものをスーパービルドして、その上にビルドできるようにしたい。自分で片付けた後、最後にスーパーを分解したい」と思います。ただし、deallocを除いて、私が使用する実質的にすべての呼び出しは構築中です。そのため、deallocコードで常に最後に表示されます。

1
user387896