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 文件,并且每个子类都有自己的映射呢?(理想情况下无需像我一样复制和粘贴代码)

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 回答