关于何时最好使用,我有点困惑:
static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";
而不是
#define AppQuitGracefullyKey @"AppQuitGracefully"
我在C或C ++中看到过这样的问题,我认为这里的不同之处在于,这是针对Objective C的,利用对象,而在像iPhone这样的设备上,可能有堆栈,代码空间或记忆问题,我还没有掌握。
一种用法是:
appQuitGracefully = [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];
或者只是风格问题?
感谢。
答案 0 :(得分:59)
如果使用静态,编译器将在二进制文件中只嵌入一个字符串副本,只是将指针传递给该字符串,从而产生更紧凑的二进制文件。如果使用#define,则每次使用时都会在源中存储单独的字符串副本。常量字符串合并将处理许多重复,但是您无需任何理由使链接器更加努力。
答案 1 :(得分:14)
见"static const" vs "#define" vs "enum"。 static
的主要优点是类型安全。
除此之外,#define
方法引入了内联字符串连接的灵活性,这是静态变量无法实现的,例如。
#define ROOT_PATH @"/System/Library/Frameworks"
[[NSBundle bundleWithPath:ROOT_PATH@"/UIKit.framework"] load];
但这可能不是一个好的风格:)。
答案 2 :(得分:4)
在做了一些搜索(this问题/答案等)后,我认为重要的是要说当你使用字符串文字@"AppQuitGracefully"
时,任何时候都会创建常量字符串,无论多少你使用它的次数会指向相同的对象。
所以我认为(如果我错了,我向我道歉)上述答案中的这句话是错误的:If you use a #define, there will be a separate copy of the string stored in the source on each use.
答案 3 :(得分:4)
我实际上不会推荐,你应该使用extern
代替。 Objective-c已定义FOUNDATION_EXPORT
more portable而不是extern
,因此全局NSString
实例看起来像这样:
·H
FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;
的.m
NSString * const AppQuitGracefullyKey = @"AppQuitGracefully";
我通常将它们放在声明文件(例如MyProjectDecl.h
)中,并在需要时导入。
这些方法存在一些差异:
#define ((int)1)
),但重点是什么?此外,该方法存在调试缺点。编译器更喜欢常量。请参阅this讨论。静态和外部的能见度不同。同样值得注意的是,这些方法都没有重复字符串(甚至不是#define
),因为编译器使用String Interning来防止这种情况。在this NSHipster post中,他们会出示证据:
NSString *a = @"Hello";
NSString *b = @"Hello";
BOOL wtf = (a == b); // YES
只有当两个变量指向同一个实例时,运算符==
才会返回YES
。正如你所看到的,确实如此。
结论是:对全局常量使用FOUNDATION_EXPORT
。它的调试友好,并且可以在整个项目中显示。
答案 4 :(得分:3)
当我需要从库或框架中导出NSString符号时,我使用static
。当我在很多地方需要一个字符串时,我可以使用#define
来轻松更改。无论如何,编译器和链接器将负责优化。
答案 5 :(得分:3)
使用#define:
您无法调试标识符
的值使用#define和其他宏是预处理器的工作, 当你首先点击构建/运行它将预处理源代码,它将适用于所有的宏(从符号#开始),
假设您已创建,
#define LanguageTypeEnglish @"en"
并在代码中的2个位置使用它。
NSString *language = LanguageTypeEnglish;
NSString *languageCode = LanguageTypeEnglish;
它会在所有地方用@"en"
替换“LanguageTypeEnglish”。
因此将生成2份@"en"
副本。
即
NSString *language = @"en";
NSString *languageCode = @"en";
请记住,在此过程中,编译器不在图片中。
预处理完所有宏后,编译器出现在图片中,它会得到这样的输入代码,
NSString *language = @"en";
NSString *languageCode = @"en";
并编译它。
使用静态
它尊重范围并且是类型安全的。 你可以调试标识符的值
在编译过程中如果找到编译器,
static NSString *LanguageTypeRussian = @"ru";
然后它将检查先前存储的同名变量, 如果是,它只会传递该变量的指针, 如果不是,它将创建该变量并传递它的指针,下次它将只传递相同的指针。
因此,使用static,在范围内只生成一个变量副本。