2

同じクラスから継承する 2 つのクラスがあります。各クラスには、クラスと同じ名前の対応する JSON ファイルがあります。インスタンスが作成されるたびに JSON が読み込まれるのを避けるために、クラス メソッドと静的変数を追加しました。

static NSArray *map = nil;
+(NSArray *)map {
    if (!map) {
        map = [NSJSONSerialization JSONObjectWithData:
       [NSData dataWithContentsOfFile:
          [[NSBundle mainBundle] pathForResource:NSStringFromClass([self class])
                                           ofType:@"json"]]
                              options:0
                                error:nil];
    }
    return map;
}

このメソッド (文字通りコピーして貼り付けたもの) を両方のサブクラスに追加しました。

これをスーパークラスに移動したいのですが、そうすると、静的変数が両方のサブクラスのインスタンス間で共有され、最初に作成されたインスタンスを持つクラスに対応する JSON マップのみが読み込まれ、後続のすべてが読み込まれます。他のクラスのインスタンスは間違ったマップを返します。

では、対応する JSON ファイルをサブクラスごとに 1 回だけロードし、各サブクラスに独自のマップを持たせるにはどうすればよいでしょうか? (理想的には、コードをコピーして貼り付けないでください)

4

2 に答える 2

2

基本クラスでは、静的なNSMutableDictionaryを保持します。クラスの名前をキーとして使用します(つまり、NSStringFromClass(childClass)を使用します)。

@interface BaseClass : NSObject

+(NSArray*)map;

@end

@interface OneChild : BaseClass

@end

@interface TwoChild : BaseClass

@end

@implementation BaseClass

+(NSArray*)map
{
        static NSMutableDictionary *_mapStore;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _mapStore = [[NSMutableDictionary alloc]init];
        });

    NSString *name = NSStringFromClass([self class]);
    NSArray *map = [_mapStore objectForKey:name];
    if(map == nil)
    {
        map = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:@"json"]] options:0 error:nil];
                [_mapStore setObject:map forKey:name];
    }
    return map;
}

@end

@implementation OneChild

@end

@implementation TwoChild

@end
于 2013-01-31T00:52:18.060 に答える
0

IMO、これを行う最もクリーンな方法は、すでに行っているように、各サブクラスで静的変数を宣言することです。マップをロードするのはコードの複製ですが、マップはクラススコープごとに異なる必要があるため、それほど不便ではないと思います。

本当にロードロジックとストレージをスーパークラスに配置したい場合は、次のように、静的変数を単なる配列ではなくディクショナリにします。

static NSMutableDictionary *maps = nil;
+(NSArray *)map {
    if (!maps) {
        maps = [[NSMutableDictionary alloc] initWithCapacity:2];
    }

    if (![maps objectForKey:[self class]]) {
        [maps setObject:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:NSStringFromClass([self class]) ofType:@"json"]] options:0 error:nil] forKey:[self class]];
    }

    return [maps objectForKey:[self class]];
}
于 2013-01-31T00:52:53.840 に答える