ios 静态 NSString 使用与内联 NSString 常量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1937685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:42:18  来源:igfitidea点击:

static NSString usage vs. inline NSString constants

iosobjective-cnsstring

提问by sickp

In Objective-C, my understanding is that the directive @"foo" defines a constant NSString. If I use @"foo" in multiple places, the same immutable NSString object is referenced.

在Objective-C 中,我的理解是指令@"foo" 定义了一个常量NSString。如果我在多个地方使用 @"foo",则引用相同的不可变 NSString 对象。

Why do I see this code snippet so often (for example in UITableViewCell reuse):

为什么我经常看到这个代码片段(例如在 UITableViewCell 重用中):

static NSString *CellId = @"CellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellId];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellId];

Instead of just:

而不仅仅是:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId"];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:@"CellId"];

I assume it is to protect me from making a typo in the identifier name that the compiler wouldn't catch. But If so, couldn't I just:

我认为这是为了保护我免于在标识符名称中输入编译器无法捕获的拼写错误。但如果是这样,我不能只是:

#define kCellId @"CellId"

and avoid the static NSString * bit? Or am I missing something?

并避免静态 NSString * 位?或者我错过了什么?

回答by Tom Dalling

It's good practice to turn literals into constants because:

将文字转换为常量是一种很好的做法,因为:

  1. It helps avoid typos, like you said
  2. If you want to change the constant, you only have to change it in one place
  1. 它有助于避免打字错误,就像你说的
  2. 如果你想改变常量,你只需要在一个地方改变它

I prefer using static const NSString*static NSString* constbecause it's slightly safer than #define. I tend to avoid the preprocessor unless I really need it.

我更喜欢使用,因为它比. 我倾向于避免使用预处理器,除非我真的需要它。static const NSString*static NSString* const#define

回答by Alex Gray

I love all the answers here without a simple example of how to correctly declare one... so...

我喜欢这里的所有答案,没有一个简单的例子来说明如何正确声明一个……所以……

If you want the constant to be externally visible (ie. "global").... declare it as such in a header...

如果您希望常量在外部可见(即“全局”)......在标题中声明它......

extern NSString *const MyTypoProneString;

extern NSString *const MyTypoProneString;

and define it in a .mfile, OUTSIDEany @implementationlike...

并将其定义在一个.m文件中,在任何类似的OUTSIDE 之外@implementation...

NSString * const MyTypoProneString = @"iDoNtKnOwHoW2tYpE";

NSString * const MyTypoProneString = @"iDoNtKnOwHoW2tYpE";

That said... if you simply want a static constthat IS LOCALto your class' implementation (or even a certain method!)... simply declare the string INSIDEthe implementation (or method) as...

也就是说......如果你只是想要一个对于你的类的实现(甚至是某个方法!static const来说是本地的......只需将实现(或方法)内部的字符串声明为......

static NSString *MavisBeacon = @"She's a freakin' idiot";

static NSString *MavisBeacon = @"She's a freakin' idiot";

EDITAlthough I do show how to do this... I have yet to be convinced that this style is in any way betterthan the ridiculously shorter, simpler, and less repetitive SINGLE declaration, á la..

编辑虽然我确实展示了如何做到这一点......我还没有相信这种风格在任何方面都比可笑的更短,更简单,更少重复的 SINGLE 声明更好,á la..

#define SomeStupidString @"DefiningConstantsTwiceIsForIdiots"

Use #define's... they are way less annoying.. Just don't let the preprocessor-player-haters get you down.

使用#define's...它们不会那么烦人...只是不要让预处理器-玩家-仇恨者让您失望。

回答by outis

You should make the static variable const.

您应该制作静态变量const

One difference between static variable and a macro is that macros don't play well with debuggers. Macros also aren't type-safe.

静态变量和宏之间的一个区别是宏不能很好地与调试器配合使用。宏也不是类型安全的。

Much of the static-var-vs-macro advice for Cand C++applies to Obj-C.

大部分针对CC++的 static-var-vs-macro 建议适用于 Obj-C。

回答by kiamlaluno

It is not guaranteed that when using @"foo"in multiple places the runtime uses the same storage for them, and certainly may not be the case across compilation unit or library boundaries.
I would rather use static NSString *string = @"foo", especially with a lot of literal strings.

不能保证@"foo"在多个地方使用时,运行时为它们使用相同的存储,当然跨编译单元或库边界可能不是这种情况。
我宁愿使用static NSString *string = @"foo",尤其是使用大量文字字符串时。

回答by Darren

I assume it is to protect me from making a typo in the identifier name that the compiler wouldn't catch.

我认为这是为了保护我免于在标识符名称中输入编译器无法捕获的拼写错误。

Correct. It's just basic defensive programming practice. The compiled result (hopefully) is the same either way.

正确的。这只是基本的防御性编程实践。无论哪种方式,编译结果(希望如此)都是相同的。

But If so, couldn't I just:

#define kCellId @"CellId"

and avoid the static NSString * bit? Or am I missing something?

但如果是这样,我不能只是:

#define kCellId @"CellId"

并避免静态 NSString * 位?或者我错过了什么?

Yes. But the kCellIdsymbol would be globally defined, at least in your compilation unit. Declaring a static variable makes the symbol local to that block.

是的。但是该kCellId符号将是全局定义的,至少在您的编译单元中是这样。声明一个静态变量使符号局部于该块。

You will typically see string constants defined as global variables or static variables rather than preprocessor defines. This helps ensure that you're only dealing with a single string instance between different compilation units.

您通常会看到定义为全局变量或静态变量而不是预处理器定义的字符串常量。这有助于确保您只处理不同编译单元之间的单个字符串实例。

回答by Matt S.

So, I'm coming into this a little late, but this has been asked numerous times in various ways in both the C / C++ areas of SO, but basically here's an expanded version of my comment to alex gray:

所以,我进入这个有点晚了,但是在 SO 的 C/C++ 领域已经以各种方式多次问过这个问题,但基本上这里是我对亚历克斯格雷的评论的扩展版本:

Anytime you think you should use a #define for string macros, you mostly likely shouldn't. The reason is because #define macros are basically regex replacements to the preprocessor. Anytime the preprocessor sees a macro called, it replaces it with whatever you defined. This means a newstring literal every single time will get allocated into memory, which is really bad in places like cell reuse identifiers (thus why Apple's UITableViewController default code uses a static).

任何时候您认为应该对字符串宏使用 #define 时,您很可能不应该这样做。原因是因为#define 宏基本上是预处理器的正则表达式替换。任何时候预处理器看到一个被调用的宏,它都会用你定义的任何东西替换它。这意味着每次都会将一个新的字符串文字分配到内存中,这在单元格重用标识符等地方非常糟糕(因此 Apple 的 UITableViewController 默认代码使用静态代码)。

Using extern / static const instead points all references to a single place in memory, as Eonil mentioned. This is much more memory efficient and performant, which is very important on mobile devices.

正如 Eonil 所提到的,使用 extern / static const 将所有引用指向内存中的一个位置。这可以提高内存效率和性能,这在移动设备上非常重要。