2010-02-26 40 views
10

我看到很多Objective-C代码,它们只是定义它需要的局部常量,然后继续其快乐的方式。问题是,据我所知,#defines没有作用域。其中许多是苹果自己的示例代码。例如,在TableViewSuite例5,在TimeZoneView.m中的drawRect函数包含以下块:Objective-C中局部常量的最佳实践

#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 

是有一些原因,我不明白,这不是荒谬的危险吗?至少,我们不应该在函数结束时使用这些常量吗?

这是我的问题,我想:

它是一个更好的做法来定义你需要它在文件中需要什么,并在年底取消定义的呢?或者你认为只使用静态常量来处理这类事情会更好吗?使用静态常量有没有任何性能损失,还是编译器能够像#define一样高效地处理它们?

回答

13

#defines在实现文件(.m)中的定义范围是它们所在的文件,因为没有其他文件。 (您要仔细想想这个共同的头文件,其中你提到的作用域的问题是真实的,SO_QUESTION_2345197_NAMESPACE_YOUR_CONSTANTS_APPROPRIATELY。)

对于实现文件的本地常量这是你似乎什么要问,#define编译效率更高,但在调试时不会得到符号。本地const有益处,并且在某些情况下(字符串常量可能依赖)可以防止二进制文件中的常量数据重复,尽管在这个世界上,大小和编译效率(以及查看它们的运行时效率)基本上是噪音,除非你分析一些紧张的循环,并找到它的问题。

+1

很酷,谢谢本,我认为那是答案。我确实认为这可能是微不足道的,但是微不足道的事情可以加起来,而其他所有事情都是平等的,我更喜欢养成默认使用高性能约定的习惯。这样,当你遇到一个重要的案例时,你已经习惯了这样做。 – DougW 2010-02-26 22:32:27

+1

字符串常量,即用@“”定义的那些是单态/原子,它们确实说了很多内存和时间。 NSNumbers是相同的方式。在任何给定的过程中,只有一个由[NSNumber numberWithInt:1]生成的实例。 – TechZen 2010-02-26 23:39:04

+0

NSNumber实习一个小的子集,而不是整个整数范围,而恒定的NSStrings将始终被实施 – rpetrich 2010-02-27 01:10:34

8

最近,我开始使用类方法来存储常量。我把它作为一个黑客来存储密钥名称在一个不合理的巨大核心数据模型中。但是,它在代码和代码库创建和维护方面都被证明是非常有效的。我产生像这样一类:

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

@implementation MyClass (KeyNames) 

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

然后我使用它像:

NSString *key=[MyClass creationDate_Key]; 

我有一个生成对我的方法的脚本。整洁的事情是,它们的范围,继承和比长定义更紧凑。如果我需要使用密钥,就像在一个循环中一样,如果效率成为问题,我就把它放在一个局部变量中。

+2

只要好奇,当你这样做的时候,每当你引用'creationDate_Key'时,它是否会在内存中创建一个新的'NSString'对象('@“creationDate”')? – 2012-07-26 20:50:26

+0

不,它不。用@创建的字符串是特殊的。 – 2012-08-14 12:11:27