objective c - Objective-C中的常量
cocoa constants (9)
你應該創建一個頭文件
// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.
(如果您的代碼不會用於混合C / C ++環境或其他平台,則可以使用extern
而不是FOUNDATION_EXPORT
)
您可以將此文件包含在每個使用常量的文件中或項目的預編譯頭文件中。
你可以在.m文件中定義這些常量
// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";
Constants.m應該被添加到你的應用程序/框架的目標中,以便它被鏈接到最終產品中。
使用字符串常量而不是stringInstance == MyFirstConstant
常量的優點是可以使用比字符串比較快得多的指針比較( stringInstance == MyFirstConstant
)來測試相等性( [stringInstance isEqualToString:MyFirstConstant]
)(並且更易於閱讀, IMO)。
我正在開發一個Cocoa應用程序,並且使用常量NSString
s來存儲我的首選項的關鍵名稱。
我知道這是一個好主意,因為如果需要,它可以輕鬆更改密鑰。 另外,它是整個“將您的數據從邏輯中分離出來”的概念。
無論如何,是否有一種好方法可以為整個應用程序定義這些常量? 我相信這是一種簡單而明智的方式,但現在我的課程重新定義了他們使用的課程。
嘗試使用類方法:
+(NSString*)theMainTitle
{
return @"Hello World";
}
我有時候會用它。
如果你想要像全局常量那樣的東西; 一個骯髒的方法是將常量聲明放入pch
文件中。
我使用單例類,以便我可以嘲笑類並在必要時更改常量以進行測試。 常量類看起來像這樣:
#import <Foundation/Foundation.h>
@interface iCode_Framework : NSObject
@property (readonly, nonatomic) unsigned int iBufCapacity;
@property (readonly, nonatomic) unsigned int iPort;
@property (readonly, nonatomic) NSString * urlStr;
@end
#import "iCode_Framework.h"
static iCode_Framework * instance;
@implementation iCode_Framework
@dynamic iBufCapacity;
@dynamic iPort;
@dynamic urlStr;
- (unsigned int)iBufCapacity
{
return 1024u;
};
- (unsigned int)iPort
{
return 1978u;
};
- (NSString *)urlStr
{
return @"localhost";
};
+ (void)initialize
{
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
+ (id)allocWithZone:(NSZone * const)notUsed
{
return instance;
}
@end
它是這樣使用的(注意使用常量c的簡寫 - 每次都節省了鍵入[[Constants alloc] init]
:
#import "iCode_FrameworkTests.h"
#import "iCode_Framework.h"
static iCode_Framework * c; // Shorthand
@implementation iCode_FrameworkTests
+ (void)initialize
{
c = [[iCode_Framework alloc] init]; // Used like normal class; easy to mock!
}
- (void)testSingleton
{
STAssertNotNil(c, nil);
STAssertEqualObjects(c, [iCode_Framework alloc], nil);
STAssertEquals(c.iBufCapacity, 1024u, nil);
}
@end
我通常使用Barry Wark和Rahul Gupta發布的方式。
雖然,我不喜歡在.h和.m文件中重複相同的單詞。 請注意,在以下示例中,這兩行文件中的行幾乎完全相同:
// file.h
extern NSString* const MyConst;
//file.m
NSString* const MyConst = @"Lorem ipsum";
因此,我喜歡做的是使用一些C預處理器。 讓我通過這個例子來解釋。
我有一個頭文件,它定義了宏STR_CONST(name, value)
:
// StringConsts.h
#ifdef SYNTHESIZE_CONSTS
# define STR_CONST(name, value) NSString* const name = @ value
#else
# define STR_CONST(name, value) extern NSString* const name
#endif
在我想要定義常量的.h / .m對中,我執行以下操作:
// myfile.h
#import <StringConsts.h>
STR_CONST(MyConst, "Lorem Ipsum");
STR_CONST(MyOtherConst, "Hello world");
// myfile.m
#define SYNTHESIZE_CONSTS
#import "myfile.h"
等瞧,我只有在.h文件中有關於常量的所有信息。
接受的(和正確的)答案說:“你可以在項目的預編譯頭文件中包含這個[Constants.h]文件...”。
作為新手,如果沒有進一步的解釋,我很難做到這一點 - 在你的YourAppNameHere-Prefix.pch文件中(這是Xcode中預編譯頭文件的默認名稱), 在#ifdef __OBJC__
塊中導入Constants.h 。
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Constants.h"
#endif
另外請注意,Constants.h和Constants.m文件中除了接受的答案中所描述的內容之外,絕對不應包含任何其他內容。 (沒有界面或實現)。
正如Abizer所說,你可以把它放到PCH文件中。 另一種不那麼骯髒的方法是為所有密鑰創建一個包含文件,然後將其包含在您使用密鑰的文件中,或者將其包含在PCH中。 在他們自己的包含文件中,至少給你一個地方尋找並定義所有這些常量。
稍微修改@Krizz的建議,以便它在常量頭文件包含在PCH中時正常工作,這很正常。 由於原始文件導入到PCH中,因此它不會將其重新加載到.m
文件中,因此不會獲得符號,鏈接器也不會很快樂。
但是,下面的修改允許它工作。 這有點複雜,但它有效。
你需要3個文件, .h
文件,它具有常數定義, .h
文件和.m
文件,我將分別使用ConstantList.h
, Constants.h
和Constants.m
。 Constants.h
的內容很簡單:
// Constants.h
#define STR_CONST(name, value) extern NSString* const name
#include "ConstantList.h"
和Constants.m
文件如下所示:
// Constants.m
#ifdef STR_CONST
#undef STR_CONST
#endif
#define STR_CONST(name, value) NSString* const name = @ value
#include "ConstantList.h"
最後, ConstantList.h
文件中有實際的聲明,並且全部是:
// ConstantList.h
STR_CONST(kMyConstant, "Value");
…
有幾件事要注意:
在
#undef
ing宏之後,我不得不在.m
文件中重新定義宏。我還必須使用
#include
而不是#import
才能正常工作,並避免編譯器看到先前預編譯的值。這將需要重新編譯你的PCH(可能是整個項目),只要任何值被改變,如果它們被正常分開(和重複),情況就不是這樣。
希望對某人有幫助。
// Prefs.h
extern NSString * const RAHUL;
// Prefs.m
NSString * const RAHUL = @"rahul";