Генерация реализаций @property с препроцессором C (верхний регистр символа в препроцессоре) - PullRequest
4 голосов
/ 20 июля 2011

Возможно, я пытаюсь злоупотребить препроцессором.Я хочу посмотреть, возможно ли то, что я имею в виду.

У моего класса @properties, которые имеют одинаковые тела.Я хочу генерировать эти тела с помощью макроса препроцессора.Например:

- (float) accelerometerSensitivity {
    return [dict floatForSelector:_cmd or:1];
}
- (void) setAccelerometerSensitivity:(float) n {
    [dict setFloat:n forSelector:_cmd];
    [dict writeToFile:[self globalDataFilename] atomically:YES];
}

- (float) returnSpringTension {
    return [dict floatForSelector:_cmd or:0];
}
- (void) setReturnSpringTension:(float) n {
    [dict setFloat:n forSelector:_cmd];
    [dict writeToFile:[self globalDataFilename] atomically:YES];
}
// set*ForSelector methods are in a category on NSMutableDictionary and depend on a function that translates selectors into strings:
// NSString* keyFromSelector(SEL selector);

Идея состоит в том, что вместо использования строковых литералов (или строковых констант) в качестве ключей в словаре, я получаю строку из имени селектора.Таким образом, я уверен, что написание ключа соответствует имени свойства и, по сути, получает преимущество проверки ключей словаря во время компиляции.

Что я хочу сделать, это сказать что-то вроде SELECTOR_PROPERY(accelerometerSensitivity) и получить егорасширить в геттер и сеттер.Основная трудность, с которой я столкнулся при реализации этого макроса препроцессора, заключается в создании имени сеттера из имени свойства.Мне нужно прописать первую букву имени свойства, и я не знаю, как это сделать в препроцессоре.

Ответы [ 3 ]

5 голосов
/ 20 июля 2011

Нет, вы не можете этого сделать.

Но вы можете комбинировать идентификаторы, поэтому теоретически вы можете определить это как:

MACRO(A,a,ccelerometerSensitivity)

Это несколько клугей, но это более кратко, чем альтернатива.

0 голосов
/ 20 июля 2011

На самом деле, вы, вероятно, действительно не хотите сделать это исключительно по архитектурным соображениям.

Вам, вероятно, будет лучше, если вы:

  • отделяет понятие состояние установки от постоянное состояние .То, что вы вызываете ввод-вывод при каждом крошечном маленьком изменении, ужасно неэффективно.Это также режим, изобилующий потенциальными проблемами;что произойдет, если вы перейдете к пользовательскому интерфейсу, где значения непрерывно отслеживают пользовательский интерфейс?... вы действительно не хотите дискового ввода-вывода каждый раз, когда диск / ползунок отслеживается под пальцем!

  • используйте @synthesize для всех ваших @properties и недаже объявить ивара.Воспользуйтесь возможностью инструмента генерировать точно правильные установщики / получатели для вас.

  • этот код выглядит очень похоже на то, как вы заново изобрели NSUserDefaults ?Используйте NSUserDefaults для любых предпочтений пользователя.

0 голосов
/ 20 июля 2011

Вот как я это сделаю:

#define MACRO(_a) { \
const char *name = #_a; \
NSString *getterName = [NSString stringWithUTF8String:name]; \
NSString *setterName = [NSString stringWithFormat:@"set%c%s:", toupper(name[0]), (name+1)]; \
NSLog(@"getter name: %@", getterName); \
NSLog(@"setter name: %@", setterName); \
}

По сути, вы строковый параметр макрокоманды, а затем с помощью простой функции C в верхнем регистре первой буквы и смещения, чтобы получить все после первогописьмо.

Теперь, когда вы делаете это:

MACRO(foo);
MACRO(bar);

Это регистрирует это:

2011-07-19 21:21:24.798 EmptyFoundation[16016:903] getter name: foo
2011-07-19 21:21:24.800 EmptyFoundation[16016:903] setter name: setFoo:
2011-07-19 21:21:24.801 EmptyFoundation[16016:903] getter name: bar
2011-07-19 21:21:24.802 EmptyFoundation[16016:903] setter name: setBar:

ОДНАКО, это строки .Вы не можете использовать их как имена методов.Сожалею.(

...