我正在学习Objective-C和Cocoa并且遇到过这样的声明:

Cocoa框架期望全局字符串常量而不是字符串文字用于字典键,通知和异常名称,以及一些带字符串的方法参数。

我只使用更高级别的语言,所以从来没有必要考虑字符串的细节。 字符串常量和字符串文字之间有什么区别?

===============>>#1 票数:83 已采纳

在Objective-C中,语法@"foo"NSString不可变的 文字实例。 它没有像Mike假设的那样从字符串文字中创建一个常量字符串。

Objective-C编译器通常在编译单元中执行实体文字字符串 - 也就是说,它们合并相同文字字符串的多次使用 - 并且链接器可以跨直接链接到单个二进制文件的编译单元执行其他实习。 (由于Cocoa区分了可变字符串和不可变字符串,并且文字字符串始终也是不可变的,因此这可以是直接且安全的。)

另一方面, 常量字符串通常使用如下语法声明和定义:

// MyExample.h - declaration, other code references this
extern NSString * const MyExampleNotification;

// MyExample.m - definition, compiled for other code to reference
NSString * const MyExampleNotification = @"MyExampleNotification";

这里的语法练习的要点是,通过确保在同一地址空间中的多个框架 (共享库)中只使用该字符串的一个实例,可以有效地利用字符串。 const关键字的位置很重要;它保证指针本身保持不变。)

虽然燃烧内存并不像25MHz 68030工作站那样拥有8MB内存,但是比较字符串是否需要时间。 确保大多数时间相同的字符串也将是指针相等的帮助。

例如,假设您想按名称订阅来自对象的通知。 如果对名称使用非常量字符串,则在确定对其感兴趣的人时,发布通知的NSNotificationCenter最终可能会执行大量逐字节字符串比较。 如果大多数这些比较都被短路,因为被比较的字符串具有相同的指针,这可能是一个巨大的胜利。

===============>>#2 票数:12

一些定义

文字是一个值,根据定义是不可变的。 例如: 10
常量是只读变量或指针。 例如: const int age = 10;
字符串文字是类似@""的表达式。 编译器将用NSString的实例替换它。
字符串常量是指向NSString的只读指针。 例如: NSString *const name = @"John";

关于最后一行的一些评论:

  • 这是一个常量指针,而不是一个常量对象1 objc_sendMsg 2并不关心你是否用const限定对象。 如果你想要一个不可变对象,你必须在对象3中编写不可变性。
  • 所有@""表达式确实是不可变的。 它们在编译时用的情况下更换4 NSConstantString ,这是一个专门的子类NSString具有固定存储器布局5。 这也解释了为什么NSString是唯一可以在编译时初始化的对象6

常量字符串const NSString* name = @"John"; 这相当于NSString const* name= @"John"; 这里,语法和程序员的意图都是错误的: const <object>被忽略, NSString实例( NSConstantString )已经是不可变的。

1关键字const适用于其左侧的任何内容。 如果它的左边没有任何东西,它适用于它右边的任何东西。

2这是运行时用于发送Objective-C中所有消息的函数,因此可用于更改对象状态的函数。

3示例:在const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects]; const不会阻止最后一个语句。

4重写表达式的LLVM代码是RewriteModernObjC::RewriteObjCStringLiteral

5要查看NSConstantString定义,cmd +在Xcode中单击它。

6为其他类创建编译时常量很容易,但需要编译器使用专门的子类。 这会破坏与旧版Objective-C版本的兼容性。


回到你的报价

Cocoa框架期望全局字符串常量而不是字符串文字用于字典键,通知和异常名称,以及一些带字符串的方法参数。 当你有选择时,你应该总是喜欢字符串常量而不是字符串文字。 通过使用字符串常量,您可以获得编译器的帮助来检查拼写,从而避免运行时错误。

它说文字很容易出错。 但它并没有说它们也慢。 相比:

// string literal
[dic objectForKey:@"a"];

// string constant
NSString *const a = @"a";
[dic objectForKey:a];

在第二种情况下,我使用带有const指针的键,所以改为[a isEqualToString:b] ,我可以做(a==b) isEqualToString:的实现isEqualToString:比较哈希然后运行C函数strcmp ,因此它比直接比较指针要慢。 就是常量字符串更好的原因:它们比较快,不易出错。

如果您还希望常量字符串是全局的,请执行以下操作:

// header
extern NSString *const name;
// implementation
NSString *const name = @"john";

===============>>#3 票数:3

让我们使用C ++,因为我的Objective C完全不存在。

如果将字符串存入常量变量:

const std::string mystring = "my string";

现在当你调用方法时,你使用my_string,你正在使用一个字符串常量:

someMethod(mystring);

或者,您可以直接使用字符串文字调用这些方法:

someMethod("my string");

大概是,他们鼓励你使用字符串常量的原因是因为Objective C没有“实习”; 也就是说,当你在几个地方使用相同的字符串文字时,它实际上是指向字符串的单独副本的不同指针。

对于字典键,这会产生巨大的差异,因为如果我可以看到两个指针指向同一个东西,这比必须进行整个字符串比较要便宜得多,以确保字符串具有相同的值。

编辑: Mike,C#字符串是不可变的,具有相同值的文字字符串都指向相同的字符串值。 我想其他语言也是如此,它们具有不可变的字符串。 在具有可变字符串的Ruby中,它们提供了一种新的数据类型:符号(“foo”与:foo,前者是可变字符串,后者是常用于Hash键的不可变标识符)。

  ask by Benedict Cohen translate from so

未解决问题?本站智能推荐:

6回复

iOS获取2个字符串之间的字符串

如何获得2个已知字符串之间的字符串? 例如: 我想从这个字符串中获得100。 我已经尝试过此代码,但无法正常工作。 NSLog是: 码:
2回复

使用iOS存储常量和附加字符串

我创建了一个constants.h文件来在我的iOS应用程序中存储一些全局变量。 但是,当我尝试访问它并将其追加到ViewController中时,出现很多错误。 这是我的constant.h文件的样子: 然后在我的视图控制器中,在顶部导入常量文件: 但是当我尝试使用以下
1回复

定义一个长而复杂的文字字符串

我有一个很长很复杂的字符串,里面有特殊字符。 我想将此字符串定义为变量,但是不想转义每个字符串(因为有很多)。 我记得在XML中它们为此具有特殊的语法,Objective-C是否有类似的东西? 编辑:我知道我可以将其保存在文件中并轻松加载,但是没有新文件也可以这样做吗? 我有很多..
1回复

ObjC中C#的@引号字符串文字

在C#中,有一种叫做@引号的字符串文字 ,它是这样写的@"<some text>" 。 例如, @"a\\nb"将由字符'a','\\','n'和'b'组成,而普通字符串“ a \\ nb”将由'a','\\ n'组成和“ b”。 问题是,ObjC是否有类似的东西? 字
4回复

警告:格式不是字符串文字,也没有格式参数

有人可以帮助我了解以下代码行返回的原因: 警告:格式不是字符串文字,也没有格式参数 我想要获得的输出是: xxxx_110327
2回复

Objective-C:“格式字符串不是字符串文字(可能不安全)”用宏警告

我正在使用宏来简化返回本地化字符串,如下所示: 基本上,如果你在本地化字符串文件中有一个条目,如"name" = "My name is %@"; ,打电话 将返回NSString @"My name is Foo" 然而,当我运行它时,如: 我得到“格式字符串不
1回复

用“ \\替换字符串”

我正在尝试将字符串发送到服务器。 我对其进行编码并将其设置为使用HTTP请求的正文 其中body是字符串,必须为json格式。 例如 应该是有效的 但是我接受用户的字符串,它可能包含双引号。因此,我必须在其中转义双引号(“)。例如,如果只发送一个” (硬编码
1回复

字符串分离

我有4个单词的字符串,如何将其分成2个字符串,每个字符串由两个单词组成? 编码: 我想将此字符串分成2个字符串:
1回复

目标c - 在特定字符之间将字符插入字符串

我需要在数组中每次出现的字符串之间插入一个字符。 例如: 我怎么能做到这一点? 我环顾四周但找不到一个好的解决方案。 谢谢。
1回复

在2个视图控制器之间传递字符串

我的问题很简单,但是作为一个初学者,我迷路了:D 我必须查看控制器: 查看一个呼叫视图2像这样: 如何将字符串facebookTypeRequest发送到视图控制器2?