我正在开发一个Cocoa应用程序,我使用常量nsstring作为存储我的首选项的键名的方式。

我知道这是一个好主意,因为它允许在必要时轻松更改密钥。 此外,这是整个“将数据与逻辑分离”的概念。

不管怎样,有没有一种好方法让这些常量在整个应用程序中定义一次?

我相信有一种简单而聪明的方法,但现在我的类只是重新定义它们所使用的方法。


当前回答

如果你想要全局常数;一种快速但肮脏的方法是将常量声明放入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

如果你想要全局常数;一种快速但肮脏的方法是将常量声明放入PCH文件中。

我自己有一个头专门声明常量nsstring用于首选项,如下所示:

extern NSString * const PPRememberMusicList;
extern NSString * const PPLoadMusicAtListLoad;
extern NSString * const PPAfterPlayingMusic;
extern NSString * const PPGotoStartupAfterPlaying;

然后在附带的.m文件中声明它们:

NSString * const PPRememberMusicList = @"Remember Music List";
NSString * const PPLoadMusicAtListLoad = @"Load music when loading list";
NSString * const PPAfterPlayingMusic = @"After playing music";
NSString * const PPGotoStartupAfterPlaying = @"Go to startup pos. after playing";

这种方法对我很有帮助。

编辑:注意,如果字符串在多个文件中使用,则效果最好。如果只有一个文件使用它,你可以在使用字符串的。m文件中做#define kNSStringConstant @“常量NSString”。

公认的(正确的)答案是“你可以包含这个[Constants.h]文件…在项目的预编译头中。”

作为新手,在没有进一步解释的情况下,我很难做到这一点——以下是如何做到的:pch文件(这是Xcode中预编译头文件的默认名称),在#ifdef __OBJC__块中导入Constants.h。

#ifdef __OBJC__
  #import <UIKit/UIKit.h>
  #import <Foundation/Foundation.h>
  #import "Constants.h"
#endif

还要注意Constants.h和Constants.h。M文件中除了已接受的答案中描述的内容外,绝对不应该包含任何其他内容。(没有接口或实现)。

我通常使用Barry Wark和Rahul Gupta发布的方法。

虽然,我不喜欢在.h和.m文件中重复相同的单词。 注意,在下面的例子中,这一行在两个文件中几乎是相同的:

// file.h
extern NSString* const MyConst;

//file.m
NSString* const MyConst = @"Lorem ipsum";

因此,我喜欢使用一些C预处理器机制。 让我通过例子来解释。

我有一个头文件,它定义宏STR_CONST(名称,值):

// 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文件只有。