連想参照は、うまくいくようです。基本的に、クラスオブジェクト自体にストレージを追加することができます。(NSString
ここでは、デモンストレーションのために、使用する辞書の代わりにsを使用しています。)
スーパークラス:
#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]私をイシュメールと呼んでください。
ここでの唯一の欠点は、オブジェクトが必要になるたびにアクセサメソッドを呼び出さなければならないことです。直接使用できるポインタがありません。objc_getAssociatedObject
もちろん、にアクセスできるので、アクセサーとしてスーパークラスを呼び出すこともできますkey
。