Objective-c 中局部常量的最佳实践

Posted

技术标签:

【中文标题】Objective-c 中局部常量的最佳实践【英文标题】:Best practices for local constants in objective-c 【发布时间】:2011-01-21 15:47:31 【问题描述】:

我看到很多 Objective-c 代码只是 #defines 它需要的局部常量,然后继续其愉快的方式。问题是,据我所知,#defines 没有作用域。其中很多都在 Apple 自己的示例代码中。例如TableViewSuite示例5中,TimeZoneView.m中的drawRect函数包含以下块:

#define LEFT_COLUMN_OFFSET 10
#define LEFT_COLUMN_WIDTH 130

#define MIDDLE_COLUMN_OFFSET 140
#define MIDDLE_COLUMN_WIDTH 110

#define RIGHT_COLUMN_OFFSET 270

#define UPPER_ROW_TOP 8
#define LOWER_ROW_TOP 34

#define MAIN_FONT_SIZE 18
#define MIN_MAIN_FONT_SIZE 16
#define SECONDARY_FONT_SIZE 12
#define MIN_SECONDARY_FONT_SIZE 10

有什么原因我不明白这不是荒谬的危险吗?至少,我们不应该在函数末尾#undef 这些常量吗?

我想这是我的问题:

在你需要的文件中定义你需要的东西,最后取消定义是不是更好的做法?还是您认为对这种类型的事情只使用静态常量更好?使用静态常量是否有任何性能损失,或者编译器是否能够像 #define 一样有效地处理它们?

【问题讨论】:

【参考方案1】:

#defines 在实现文件 (.m) 中的定义范围仅限于它们所在的文件,因为没有其他人 #includes 是 .m 文件。 (您确实想在常见的头文件中仔细考虑这一点,您提到的范围问题是真实的,以及 SO_QUESTION_2345197_NAMESPACE_YOUR_CONSTANTS_APPROPRIATELY。)

对于实现文件中的局部常量,您似乎在询问,#define 的编译效率更高,但在调试时您不会得到符号。本地常量有这个好处,并且在某些情况下(字符串常量?也许?取决于)防止二进制中的常量数据重复,尽管在世界上这一点上,大小和编译效率(以及查找它们的运行时效率)基本上是噪音,除非你分析一些紧密的循环并发现它的问题。

【讨论】:

很酷,谢谢 Ben,我想这可以回答这个问题。我确实同意这可能是微不足道的,但是微不足道的事情可以加起来,并且在所有其他条件相同的情况下,我更愿意养成默认使用性能约定的习惯。这样一来,当您确实遇到重要的案件时,您已经养成了这样做的习惯。 字符串常量,即用@"" 定义的那些是单例/原子,它们确实说相当多的内存和时间。 NSNumbers 是相同的方式。在任何给定的进程中,只有一个由 [NSNumber numberWithInt:1] 生成的实例。 NSNumber 实习一个小子集,而不是整个整数范围,而常量 NSStrings 将始终被实习 好答案。另外,我想补充一点,使用枚举也是在头文件和实现文件中定义数字常量的好方法,因为适当的范围规则(即名称可以被遮盖)将适用。【参考方案2】:

最近,我开始使用类方法来存储常量。我一开始是把键名存储在一个巨大的核心数据模型中。然而,事实证明,无论是在代码中还是从代码库创建和维护的角度来看,它都相当有效。我像这样生成一个类别:

@interface MyClass (KeyNames)
+ (NSString *) creationDate_Key;
@end

@implementation MyClass (KeyNames)

+ (NSString *) creationDate_Key
    return @"creationDate";
 
@end

然后我像这样使用它:

NSString *key=[MyClass creationDate_Key];

我有一个为我生成方法的脚本。巧妙的是,它们是作用域的、继承的并且比长定义更紧凑。如果我需要大量使用密钥,比如在循环中,如果效率成为问题,我只需将其停放在局部变量中。

【讨论】:

只是好奇,当你这样做的时候,是不是每次你引用creationDate_Key时都会在内存中创建一个新的NSString对象(@"creationDate")? 不,它没有。用 @ 创建的字符串是特殊的。

以上是关于Objective-c 中局部常量的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Objective-c 中更好的 JSON 解析实现和最佳实践?

在objective-c或swift中覆盖pod文件方法的最佳实践是啥?

在 laravel 中添加常量的最佳实践是啥? (长名单)

在 Java 中维护常量的最佳实践

使用objective-c块时避免泄漏的最佳实践是啥?

在objective-c中为原始类型分配内存的最佳实践