2012-01-11 5 views
4

-[NSObject dealloc]メソッドをスウィズすることによってオブジェクトが割り当て解除されたときに呼び出されるコードを記述しようとしました。私はこれが悪い考えであり、追求していないことを理解しています。(これを指摘するのは控えてください)しかし、その途中で、フリーダイヤルのNSDictionaryやNSStringなどのクラスは、CFDictionary CFStringは最終リリース時に-deallocを呼び出しません。フリーダイヤルのクラスは、コア・ファウンデーションの対応者とブリッジされて最終リリース時に-deallocを呼び出さないのはなぜですか?

このコードは、この現象を示しています。

上記のテストで
- (void)loggedDealloc { 
    NSLog(@"Deallocation of %@", self.class); 
    [self loggedDealloc]; 
} 

- (void)testDeallocSwizzleOnTestObject { 
    Method deallocMethod = class_getInstanceMethod([TestObject class], NSSelectorFromString(@"dealloc")); 
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc)); 
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 

    TestObject * testObject = [[TestObject alloc] init]; 
    testObject = nil; // calls release under ARC 

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 
} 

- (void)testDeallocSwizzleOnNSDictionary { 
    Method deallocMethod = class_getInstanceMethod([NSDictionary class], NSSelectorFromString(@"dealloc")); 
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc)); 
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 

    NSDictionary * dictionary = [[NSDictionary alloc] init]; 
    dictionary = nil; // calls release under ARC 

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 
} 

- (void)testDeallocSwizzleOnNSString { 
    Method deallocMethod = class_getInstanceMethod([NSString class], NSSelectorFromString(@"dealloc")); 
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc)); 
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 

    NSDictionary * dictionary = [[NSDictionary alloc] init]; 
    dictionary = nil; // calls release under ARC 

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod); 
} 

、TestObjectの唯一のスウィズリングは、解除のロギングが発生する原因となります。 NSDictionaryとNSStringの比較は効果がありません。

私はフリーダイヤルブリッジ・クラスは、このようにメモリがCore Foundationので割り当てが解除され、-deallocへの呼び出しが全く発生せず、代わりに[super release]を呼び出すCFReleaseを実行するために-releaseを実装しているため、これがあると思います。

これは誰でも確認できますが、それはどこに文書化されていますか?もしそうなら、これらの無料フリーダイヤルクラスの割り当て解除にカスタムコードを挿入する方法はありますか?

答えて

3

(へぇ。があった。それを完了。:) dealloc

コールが唯一の様々なクラスのサブクラスのために保証されています。 deallocは決して呼び出す必要がないので、多くのクラス(主にさまざまなCF/NSブリッジクラス)があります。[内部実装の詳細]

目的のクラスをサブクラス化し、元のクラスのインスタンスをバッキングストアとしてカプセル化し、プリミティブメソッドをオーバーライドするのははるかにクリーンです(すべてのクラスクラスタークラスは非常に最小限のセットプリミティブメソッドの - 私はNSStringは2つのメソッドのすべてを持っていると思う)、新しいクラスのメモリ管理メソッドをオーバーライドします。それはサブクラスなので、既存のクラスで見られる「短絡」はもはや機能しません。

関連する問題