Фон: Я использую тонну объектов NSDictionary в своем коде iPhone и iPad. Мне надоел многословный способ получения / установки ключей для этих государственных словарей.
Итак, небольшой эксперимент : я только что создал класс, который я называю Remap.
Remap будет принимать любой произвольный набор селектора obj [VariableName] :( NSObject *) и перенаправлять это сообщение функции, которая вставит obj во внутренний NSMutableDictionary под ключом [vairableName].
Remap также принимает любой (нулевой аргумент) произвольный селектор [variableName] и возвращает объект NSObject, сопоставленный в NSMutableDictionary под ключом [variableName].
, например
Remap * remap = [[Remap alloc] init];
NSNumber * testNumber = [NSNumber numberWithInt:46];
[remap setTestNumber:testNumber];
testNumber = [remap testNumber];
[remap setTestString:@"test string"];
NSString * testString = [remap testString];
NSMutableDictionary * testDict = [NSMutableDictionary dictionaryWithObject:testNumber forKey:@"testNumber"];
[remap setTestDict:testDict];
testDict = [remap testDict];
где ни одно из свойств testNumber, testString или testDict фактически не определено в Remap.
Сумасшедшая вещь? Это работает ... Мой единственный вопрос как я могу отключить предупреждения "может не отвечать" для JUST доступа к Remap ?
P.S. : Я, вероятно, в конечном итоге откажусь от этого и перейду к макросам, поскольку пересылка сообщений довольно неэффективна ... но кроме этого кто-нибудь видит другие проблемы с Remap?
Вот Remap's .m для любопытных:
#import "Remap.h"
@interface Remap ()
@property (nonatomic, retain) NSMutableDictionary * _data;
@end
@implementation Remap
@synthesize _data;
- (void) dealloc
{
relnil(_data);
[super dealloc];
}
- (id) init
{
self = [super init];
if (self != nil) {
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
[self set_data:dict];
relnil(dict);
}
return self;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSString * selectorName = [NSString stringWithUTF8String: sel_getName([anInvocation selector])];
NSRange range = [selectorName rangeOfString:@"set"];
NSInteger numArguments = [[anInvocation methodSignature] numberOfArguments];
if (range.location == 0 && numArguments == 4)
{
//setter
[anInvocation setSelector:@selector(setData:withKey:)];
[anInvocation setArgument:&selectorName atIndex:3];
[anInvocation invokeWithTarget:self];
}
else if (numArguments == 3)
{
[anInvocation setSelector:@selector(getDataWithKey:)];
[anInvocation setArgument:&selectorName atIndex:2];
[anInvocation invokeWithTarget:self];
}
}
- (NSMethodSignature *) methodSignatureForSelector:(SEL) aSelector
{
NSString * selectorName = [NSString stringWithUTF8String: sel_getName(aSelector)];
NSMethodSignature * sig = [super methodSignatureForSelector:aSelector];
if (sig == nil)
{
NSRange range = [selectorName rangeOfString:@"set"];
if (range.location == 0)
{
sig = [self methodSignatureForSelector:@selector(setData:withKey:)];
}
else
{
sig = [self methodSignatureForSelector:@selector(getDataWithKey:)];
}
}
return sig;
}
- (NSObject *) getDataWithKey: (NSString *) key
{
NSObject * returnValue = [[self _data] objectForKey:key];
return returnValue;
}
- (void) setData: (NSObject *) data withKey:(NSString *)key
{
if (key && [key length] >= 5 && data)
{
NSRange range;
range.length = 1;
range.location = 3;
NSString * firstChar = [key substringWithRange:range];
firstChar = [firstChar lowercaseString];
range.length = [key length] - 5; // the 4 we have processed plus the training :
range.location = 4;
NSString * adjustedKey = [NSString stringWithFormat:@"%@%@", firstChar, [key substringWithRange:range]];
[[self _data] setObject:data forKey:adjustedKey];
}
else
{
//assert?
}
}
@end