超类中的静态变量

时间:2013-01-31 00:22:39

标签: objective-c macos inheritance

我有两个继承自同一个类的类。每个类都有一个对应的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文件,每个子类都有自己的映射? (理想情况下,我没有复制和粘贴代码)

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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]];
}