为字符串常量妖魔化的 Objective-C#define 指令

标签 objective-c cocoa

我在几篇文章和 Apple 的代码指南中读到,在 Objective-C 中,字符串常量应定义为 extern NSString *const MY_CONSTANT; 并且应避免使用 #define 指令。这是为什么?我知道 #define 是在预编译时运行的,但所有字符串都将共享相同的内存地址。我读到的唯一优点是,如果必须更新或更改常量,则不必重新编译整个项目。所以这就是应该避免#define 的原因吗?

谢谢

更新:在这种情况下,使用#define 是好还是有更好的方法?

/* Constants Definition */
#define SERVER_URL @"http://subdomain.domain.edu.ar/Folder/"
NSString *const ServerURL = SERVER_URL;
NSString *const LoginURL = SERVER_URL@"welcome.asp";
NSString *const CommandURL = SERVER_URL@"com.asp";

最佳答案

使用常量而不是定义的一个实际原因是您可以进行直接比较(使用 ==)而不是使用 isEqual:。考虑:

NSString * const kSomeStringConstant = @"LongStringConstantIsLong";
...
[someArray addObject:kSomeStringConstant];
if ([someArray lastObject] == kSomeStringConstant)
{
   ...
}

这是可行的,因为 == 比较会将相同的 const 指针与单个 NSString 对象进行比较。但是,使用 #define:

#define STRING_CONSTANT @"MacrosCanBeEvil";
...
[SomeArray addObject:STRING_CONSTANT]; // a new const `NSString` is created
if ([someArray lastObject] == STRING_CONSTANT) // and another one, here.
{
    ...
}

不会成功,因为这两个字符串会有唯一的指针。要有效地比较它们,您必须使用 isEqual:

进行逐个字符的比较
if ([[someArray lastObject] isEqual:STRING_CONSTANT])
{
    ...
}

就执行时间而言,这比简单的 == 比较要昂贵得多。

另一个动机可能是可执行文件本身的大小。 #defined 常量实际上会出现在代码中使用它的任何位置。这可能意味着该字符串在您的可执行文件中多次出现。相反,常量应该(对于现代编译器)只定义一次,所有进一步的使用都将引用指向该定义的指针。

现在,在有人因为过早的优化而对我大喊大叫之前,请考虑这两种方法在实现方面几乎相同,但 const 指针方法在代码大小和执行时间方面要优越得多。

关于为字符串常量妖魔化的 Objective-C#define 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1977489/

相关文章:

ios - addSubview 不显示 UIView

ios - NSSortDescriptor - 基于另一个数组的排序描述符

ios - 编辑 mp4/m4a 文件的元标记

ios - UItableView 选择问题

cocoa - 通过类别添加 BOOL 属性

ios - 如何使用 Storyboard将两个 View Controller 连接到一个 View Controller ?

cocoa - 在cocoa2.0中,@property是否避免了接口(interface)中的变量声明

objective-c - 无法获取 NSString 的长度 - 发送到实例的选择器无法识别

objective-c - 从 NSString 中删除标记字符

cocoa - NSManagedObject 和 KVO 与文档