2011-07-20 76 views
4

我可能試圖濫用預處理器。我想看看我腦海裏有甚麼可能。使用C預處理器生成@property實現(大寫預處理器中的字符)

我的課有@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)這樣的東西,並把它擴展到getter和setter。我在實現這個預處理器宏時遇到的主要困難是從屬性名稱中生成setter名稱。我需要將屬性名稱的第一個字母大寫,並且我不知道如何在預處理器中執行此操作。

回答

5

Nope, you can't do that.

但是,你可以結合標識符,因此在理論上,你可以將此定義爲:

MACRO(A,a,ccelerometerSensitivity) 

這有點klugey,但它比其他更簡潔。

+0

是的,這是我想到的後備。感謝您確認CPP不具備執行我想要的那種操作的表達能力。 – iter

0

以下是我會做:

#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: 

然而,這些字符串。您不能將它們用作方法名稱。抱歉。 :(

0

其實,你大概真的希望建築方面的原因純粹是做

你可能會好起來的,如果你:

  • 分開的概念設置狀態持續狀態。如果每一次微小的變化都導致I/O效率非常低下,它也是一個潛在的問題模式;如果移動到UI值是否持續跟蹤用戶界面? ...每次在手指下跟蹤撥號/滑塊時,您都不希望磁盤I/O!

  • 對所有@properties使用@synthesize,甚至不聲明ivars。利用該工具爲您生成完全正確的setter/getters的能力。

  • 該代碼看起來非常像你重新發明的NSUserDefaults?使用NSUserDefaults爲任何用戶偏好kinda東西。

+0

我的問題不問我想做什麼。它_says_我想要做什麼。 --- 我想要生成的代碼是已經在源代碼中的代碼,它的執行情況令我滿意。我只問如何生成它而不是複製粘貼它。 --- 本例中除字典外沒有ivars。這是我準備繼續保持用戶設置時所需的課程。我支持分離狀態和持久性的概念 - 這是持久性部分。 --- NSUserDefaults不是答案。我的UI更加複雜,我希望它能夠在應用程序內部生存,而不是在設置的角落。 – iter

+3

NSUserDefaults *完全可用於您的應用*。它*不需要去設置*。這是用戶默認的整個點。用戶默認通常可以避免每次狀態更改時發送垃圾郵件。 – bbum

+0

感謝您的意見。它讓我感到羞恥,你知道我的應用程序中可用的東西。我對NSUserDefaults的使用經驗有限,但是我已經使用過它,它在Settings應用程序中創建UI元素(這全部在iOS上)。在任何情況下,NSUserDefaults都使用字符串鍵來查找值,而我的問題的關鍵是我想避免使用字符串文字(或解析爲文字的常量)作爲鍵。我的經驗是,如果在應用程序中有十幾個這樣的字符串鍵,拼寫錯誤就成爲一種麻煩。如果我使用NSUserDefaults,只有宏的主體發生變化。 – iter