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