0

Big Nerd Ranch の iOS Programming Book (第 3 版) の pg.194 には、知識のあるプログラマーが allocWithZone: を介して BNRItemStore のインスタンスを作成する可能性があると書かれています。 BNRItemStore.m で、単一の BNRItemStore インスタンスを返します。

+(id) allocWithZone:(NSZone *)zone
{
    return [self sharedStore];
}

このステートメントは、私には混乱しているように思えます。この次のコードは、ある意味でこれが間違っていることを証明していませんか?

#import <Foundation/Foundation.h>

@interface BNRItemStore : NSObject
+(BNRItemStore *)sharedStore;
+(id)retrieveObject;
@end
@implementation BNRItemStore
+(BNRItemStore *)sharedStore{
    static BNRItemStore *sharedStore=nil;
    if (!sharedStore){
        NSLog(@"Test2");
        sharedStore= [[super allocWithZone:nil] init];
    }
    NSLog(@"sharedStore-> %@",sharedStore);
    return sharedStore;
}
+(id)allocWithZone:(NSZone *)zone{
    NSLog(@"Test1");
    return [self sharedStore];
}
+(id)alloc{
    NSLog(@"Retrieving super object");
    NSLog(@"%@", [super allocWithZone:nil]);//Bypassing the subclass version of    allocWithZone.
    return [super allocWithZone:nil];
}
@end

int main(){
    [[BNRItemStore alloc] init]; //the alloc message triggers a call to the subclass  (overriding) version of +(id)alloc method
}

出力は次のとおりです。

  • 2013-10-18 18:24:40.132 BNRItemStore[381:707] スーパー オブジェクトの取得
  • 2013-10-18 18:24:40.134 BNRItemStore[381:707] BNRItemStore:0x7f8c72c091e0

サブクラスの 'alloc' メソッド内の [super allocWithZone:nil] 呼び出しがサブクラスの allocWithZone への呼び出しをトリガーした場合、コンソールは "Test1" と "Test2" をログに記録し、最終的に静的ポインターが割り当てられることになります。しかし、これは起こりませんでした。これは、[NSObject allocWithZone:nil] または [super allocWithZone:nil] を直接呼び出すと、メッセージは allocWithZone のオーバーライド バージョン (サブクラス バージョン) にリダイレクトされず、実際の処理を行う NSAllocateObject() 関数に直接アクセスできることを意味します。割り当て。NSObject の +(id)allocWithZone のコードは、次のようになります。

+(id)allocWithZone:(NSZone *)zone{
    return NSAllocateObject();
}

この実装 (NSObject の allocWithZone:) に [self allocWithZone] のようなものが含まれていた場合、メッセージ ディスパッチ メカニズムには allocWithZone のサブクラス バージョンが含まれており、sharedStore メソッドの呼び出しを含む「卑劣な」トラップを通過することになります。私が話しているケース。この場合、コードは間違いなく無限ループになります。明らかに、そうではありません。

+(id)allocWithZone:(NSZone *)zone{
    if([self allocWithZone:zone])      //this would trigger a call to subclass ver. which would call sharedStore method which would then have [super allocWithZone:nil].Infinite Loop
    return NSAllocateObject();
}

誰かがこのいわゆる「卑劣な」トラップに関するこのクエリをクリアできますか。トラップは、誰かが個別にインスタンス化するのをブロックするためのものでした.つまり、sharedStoreメソッド内以外ではNSObjectのallocWithZoneを使用できませんか? Plsは明確に..

4

2 に答える 2

0

これがあなたの質問に完全に答えるかどうかはわかりませんが、割り当てられたメモリを分割できるようにするために、「allocWithZone:」が使用されていました。その後、apple はこの概念から離れ、すべてが同じヒープ領域に割り当てられることを期待しています。「allocWithZone:」は以前のようには機能しません。Apple は特に使用しないように指示しています。

于 2013-10-18T17:35:01.013 に答える