我的iOS应用程序中有以下类(它就像来自Java世界的抽象类)。
@implementation WSObject
static NSDictionary* _dictionary = nil;
+(NSDictionary*) dictionary {
if (_dictionary == nil) {
_dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
return _dictionary;
}
...
@end
然后我有多个类使用类方法WSObject
实现上面的dictionary
。问题是,这些类中的每一个都应该有自己的_dictionary
,但它们都是从超类共享同一个对象。当然,我可以复制到所有子类,但这会破坏可重用性。除了这个getter之外,WSObject
中还有其他类方法可以改变字典。因此,每个子类都应该有几个类方法。
如何以智能方式解决这个问题?如果我的描述不充分,请告诉我。
答案 0 :(得分:9)
Associative references似乎他们会做的伎俩。您实际上可以在类对象本身上添加一些存储空间。 (我在这里使用NSString
代替您想要使用的词典,仅用于演示。)
超类:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Stuper : NSObject
// Accessor method for the "class variable"
+ (NSString *) str;
// Analog to your +localStorePath
+ (NSString *) quote;
@end
#import "Stuper.h"
// The doc suggests simply using the address of a static variable as the key.
// This works fine, even though every class is (as in your problem) using
// the same key, because we are associating to a different class each time.
static char key;
@implementation Stuper
+ (NSString *) str {
NSString * s = objc_getAssociatedObject(self, &key);
if( !s ){
s = [self quote];
// You'll probably want to use OBJC_ASSOCIATION_RETAIN for your dictionary.
// self inside a class method is the class object; use that as
// the associator. The string is now tied to the associator, i.e.,
// has the same lifetime.
objc_setAssociatedObject(self, &key, s, OBJC_ASSOCIATION_COPY);
}
return s;
}
+ (NSString *) quote {
return @"It was the best of times, it was the worst of times.";
}
@end
<小时/> <小时/>
子类:
#import "Stuper.h"
@interface Stub : Stuper @end
#import "Stub.h"
@implementation Stub
+ (NSString *) quote {
return @"Call me Ishmael.";
}
@end
<小时/> <小时/>
试试这个:
#import <Foundation/Foundation.h>
#import "Stuper.h"
#import "Stub.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"%@", [Stuper str]);
NSLog(@"%@", [Stub str]);
[pool drain];
return 0;
}
每个类对象现在都有自己的字符串,与之关联。
2011-12-05 23:11:09.031 SubClassVariables [36254:903]这是最好的时期,这是最糟糕的时期。
2011-12-05 23:11:09.034 SubClassVariables [36254:903]叫我Ishmael。
这里唯一的缺点是你每次想要对象时都必须调用访问器方法;你没有可以直接使用的指针。当然,您也可以将超类中的objc_getAssociatedObject
称为访问者,因为它可以访问key
。
答案 1 :(得分:7)
为了给每个子类提供自己的字典,使用类名作为键在主字典中存储第二个字典对象。例如:
static NSMutableDictionary *_dictionary = nil;
+ (NSDictionary*)dictionary
{
if (_dictionary == nil)
_dictionary = [[NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]] mutableCopy];
NSString *key = NSStringFromClass( [self class] );
if ( [_dictionary objectForKey:key] == nil )
[_dictionary setObject:[NSMutableDictionary dictionary] forKey:key];
return [_dictionary objectForKey:key];
}
答案 2 :(得分:2)
也许您可以返回字典的副本
@implementation WSObject
static NSDictionary* _dictionary = nil;
+(NSDictionary*) dictionary {
if (_dictionary == nil) {
_dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
return [_dictionary copy];
}
...
@end
请记住,如果您修改_dictionary
,您将获得该修改后的字典的副本,该副本可能与磁盘上的字典不同。
这种情况多久被召唤一次?是否真的有必要在这个静态_dictionary
对象中缓存文件内容?
为什么不在每次表单磁盘时获取它,假设性能不是经常出现问题。
@implementation WSObject
+(NSDictionary*) dictionary {
return [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]];
}
...
@end