首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我应该更喜欢使用文字语法或构造函数来创建字典和数组吗?

我应该更喜欢使用文字语法或构造函数来创建字典和数组吗?
EN

Stack Overflow用户
提问于 2012-09-21 18:07:11
回答 3查看 1.9K关注 0票数 3

我正在阅读iOS开发人员指南,以熟悉objects语言,目前我在容器文字和子脚本符号的主题上有点混乱,因为它涉及创建像NSDictionary这样的对象。

我理解有几种方法可以创建NSDictionary对象,包括键值编码(dictionaryWithObjects:forKeys:dictionaryWithObjectsAndKeys:,或相应的初始化器)。源链接

根据我的理解,有两种主要的方法可以做到这一点,然后是--另一种方法--通过使用容器文本,在这里演示:

代码语言:javascript
复制
NSDictionary *myDictionary = @{
   @"name" : NSUserName(),
   @"date" : [NSDate date],
   @"processInfo" : [NSProcessInfo processInfo]
};

使用哪一种方法最好?与前两种技术相比,使用容器文字技术有什么好处吗?还是对程序员来说只是一件方便的事情呢?

我的印象是,这也是另一种更容易的方式来编码类似数组的东西。这是真的还是我在这里错过了什么?这些技术仅仅是个人偏好的问题吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-23 21:09:12

我不同意目前发布的其他答案:几乎所有时候,使用新的容器字面语法都比使用构造函数好。它们有助于提高代码的正确性,而且对于兼容性也没有太多的担忧。

代码正确性

容器文字确实是语法糖,但具体而言,它们映射到“安全”构造器方法+[NSArray arrayWithObjects:count:]+NSDictionary dictionaryWithObjects:forKeys:count:。直接使用这些方法之一构造数组或字典并不太方便,因此许多程序员发现使用arrayWithObjects:dictionaryWithObjectsAndKeys:更简单。但是,后一种方法有一个严重的缺陷:因为参数列表必须用nil终止,所以如果要传递对象的nil,您可能会发现自己有意想不到的数组/字典内容。

例如,假设您正在建立一个字典,映射您的一个模型对象的属性(也许您要以JSON的形式发送它?):

代码语言:javascript
复制
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
    person.name, @"name", person.title, @"title", person.address, @"address", 
    nil];

如果这段代码遇到没有为其设置Persontitle,则生成的字典将丢失@"address"键及其值。您可以花上几个小时来查找数据库中的一些人丢失地址的原因(甚至看到上面的代码并将您的头发撕掉,不知道为什么当我设置它的时候,它不起作用!)我们很多人都有。

相反,如果您使用如下的文字形式:

代码语言:javascript
复制
NSDictionary *dictionary = @{
    @"name": person.name, @"title": person.title, @"address": person.address };

它将扩展到这样的内容:

代码语言:javascript
复制
id objects[] = { person.name, person.title, person.address };
id keys[] = { @"name", @"title", @"address" };
NSUInteger count = sizeof(objects) / sizeof(keys);
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects
                                                       forKeys:keys
                                                         count:count];                          

如果person.nameperson.title返回nil,此方法将抛出一个异常,而不是默默地创建您不想要的数据。(无论哪种方式,您都必须决定如何使用代码来处理nil标题,但这样您就能更快地解决问题。)当然,您可以自己编写这个“更安全”的表单,而不是使用等效的语法糖,但您确定您不会因为dictionaryWithObjectsAndKeys:更短而放弃编写它的习惯吗?

兼容性

容器文本(以及数字文字和装箱表达式 )生成的代码不使用新的API,因此您可以使用Xcode 4.4或更高版本(或Clang3.1或更高版本)编译它,并将其部署到任何版本的Foundation。但是,如果您的源代码也将与旧的编译器或GNUStep一起使用,则需要考虑兼容性。(虽然听起来GNUStep现在也很适合Clang。)

这不是问题的一部分,但因为它涉及一个相关的主题:对于新的对象订阅语法来说,这也是“某种意义上的”。它只使用在MacOSX10.6和iOS 6.0上定义的新方法.但是这些方法都是由libarclite提供的。(您知道,当您尝试将ARC代码部署回iOS 4.3或MacOSX10.6时,就会链接到这个库中-它不再仅仅用于iOS!)所以,您所需要做的就是在一个标题中声明它们,如果您还没有这样做,就链接ARCLite,这样就可以了。

票数 12
EN

Stack Overflow用户

发布于 2012-09-21 18:26:50

没有“最好的办法”。对一个特定的用例使用最合适的方法。例如,如果您希望您的应用程序是可移植的(即只需要基金会而不需要UIKit的逻辑也可以在其他平台上运行,比如Mac或带有GNUstep的Linux等等)。然后避免使用文字语法--它们不是很容易移植。如果您只需要它在iOS上工作,那么就使用它们,因为它们很方便。

而且,这些符号只是语法糖--也就是说,它们映射到方法名称(据我所知,准确地映射到您在问题中提到的两种方法),因此它们对性能、算法的行为等没有任何影响。

是的,您猜对了:这同样适用于新的订阅语法--对于NSArray,它调用- objectAtSubscriptedIndex:

票数 2
EN

Stack Overflow用户

发布于 2012-09-22 16:50:01

您可以在GNU/Linux上与GNUstep和clang一起使用它们。在我的大多数情况下,GNUstep的作品比gcc的所有版本都要好得多。(对不起,我应该编辑另一个答案,我是新手)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12535855

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档