我是否应该使用文字语法或构造函数来创建字典和数组? [英] Should I prefer to use literal syntax or constructors for creating dictionaries and arrays?

查看:99
本文介绍了我是否应该使用文字语法或构造函数来创建字典和数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读iOS开发者指南以熟悉Objective-C语言,目前我对容器字面量和下标表示法的话题有些困惑,因为它与创建NSDictionary之类的对象有关.

I am reading through the iOS Developer Guide to get familiarized with the Objective-C language and currently I am having a little confusion on the topic of Container Literals and Subscript Notation as it pertains to creating objects like NSDictionary.

我了解有多种创建NSDictionary对象的方法,包括键-值编码(dictionaryWithObjects:forKeys:dictionaryWithObjectsAndKeys:或其对应的初始化程序). 源链接.

I understand that there are several ways to create NSDictionary objects including Key-Value encoding (dictionaryWithObjects:forKeys: and dictionaryWithObjectsAndKeys:, or their corresponding initializers). Source Link.

根据我的理解,有两种主要的方法可以做到这一点,然后有另一种的方法是使用容器文字,如下所示:

From my understanding there are two main ways to do this and then there is another way which is by using container literals, demonstrated here:

NSDictionary *myDictionary = @{
   @"name" : NSUserName(),
   @"date" : [NSDate date],
   @"processInfo" : [NSProcessInfo processInfo]
};

哪种是最佳使用方式?使用Container Literal技术比前两个有什么好处,还是对程序员来说只是方便的事情?

Which is the best way to use? Is there any benefit in using the Container Literal technique over the previous two or is it just a convenience thing for programmers?

我的印象是,这也是对诸如数组之类的东西进行编码的另一种简便方法.这是真的吗?或者我在这里缺少什么?这些技术只是个人喜好吗?

I am under the impression that it is also just another easier way to code things like arrays. Is this true or is there something that I'm missing here? Are these techniques just a matter of personal preference?

推荐答案

我不同意到目前为止发布的其他答案:几乎所有时候,使用新的容器文字语法比使用构造函数要好.它们有助于提高代码的正确性,并且实际上不必担心兼容性.

I disagree with the other answers posted thus far: almost all the time, it's better to use the new container literal syntax than to use constructors. They help with code correctness, and there's not really that much to worry about for compatibility.

容器字面量确实是语法糖,但具体来说,它们映射到安全"构造函数方法 +NSDictionary dictionaryWithObjects:forKeys:count: .直接使用这些方法之一构造数组或字典并不是很方便,因此许多程序员发现使用arrayWithObjects:dictionaryWithObjectsAndKeys:更简单.但是,后一种方法有一个陷阱:由于参数列表必须以nil结尾,因此如果在打算传递对象的地方传递nil,则会发现自己具有意外的数组/字典内容.

Container literals are indeed syntactic sugar, but specifically they map to the "safe" constructor methods +[NSArray arrayWithObjects:count:] and +NSDictionary dictionaryWithObjects:forKeys:count:. Constructing an array or dictionary using one of these methods directly isn't all that convenient, so many programmers find it simpler to use arrayWithObjects: and dictionaryWithObjectsAndKeys:. However, the latter methods have a nasty pitfall: since the argument list must be terminated with nil, you can find yourself with unexpected array/dictionary contents if you pass nil where you intend to pass an object.

例如,假设您正在建立一个字典,该字典映射一个模型对象的属性(也许您将其作为JSON发送?):

For example, say you're setting up a dictionary mapping the properties of one of your model objects (maybe you're going to send it as JSON?):

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
    person.name, @"name", person.title, @"title", person.address, @"address", 
    nil];

如果此代码遇到未设置titlePerson,则结果字典将丢失@"address"键及其值.您可能需要花费数小时来追踪为什么数据库中的某些人缺少地址(甚至看到上面的代码并把头发弄乱了,想知道为什么来的时候它不起作用,我在这里设置它" !).我们很多人都有.

If this code runs into a Person for whom no title has been set, the resulting dictionary will be missing the @"address"key and its value. You could spend hours tracking down why some fraction of the people in your database are missing addresses (and even see the code above and tear your hair out wondering why it's not working when c'mon, I'm setting it right there!). Many of us have.

相比之下,如果您使用如下文字形式:

By contrast, if you use the literal form like this:

NSDictionary *dictionary = @{
    @"name": person.name, @"title": person.title, @"address": person.address };

它将扩展为以下内容:

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:短而放弃它的习惯了吗?

And if person.name or person.title returns nil, this method will throw an exception instead of silently creating data you don't want. (Either way you'll have to decide how you want your code to handle nil titles, but this way you'll catch the problem sooner.) And sure, you could write this "safer" form yourself instead of using the equivalent syntactic sugar, but are you sure you won't just fall back on the habit of writing dictionaryWithObjectsAndKeys: because it's shorter?

由容器文字(和数字文字和带框表达式生成的代码)不使用新的API,因此您可以使用Xcode 4.4或更高版本(或直接Clang 3.1或更高版本)进行编译,并部署到任何版本的Foundation.但是,如果您的源代码也将与较早的编译器或GNUStep一起使用,则需要考虑兼容性. (虽然听起来GNUStep现在也适用于Clang.)

The code generated by container literals (and number literals and boxed expressions, for that matter) uses no new API, so you can compile it with Xcode 4.4 or newer (or Clang 3.1 or newer directly) and deploy to any version of Foundation. You do need to consider compatibility if your source code will also be used with older compilers or GNUStep, however. (Though it sounds like GNUStep is good with Clang now, too.)

这不是问题的一部分,但是因为它涉及到一个相关的主题:对于新对象下标语法,情况也是如此.这确实使用了仅在Mac OS X 10.6和iOS 6.0上定义的新方法...,但是这些方法由libarclite提供. (您知道,当您尝试将ARC代码部署回iOS 4.3或Mac OS X 10.6时,已链接的库–不再仅适用于ARC!)因此,您所需要做的就是在标头中声明它们,链接如果您还没有ARCLite,那您就很好了.

And it's not part of the question, but since it's on a related subject: the same is "sort of" true for the new object subscripting syntax. That does use new methods only defined on Mac OS X 10.6 and iOS 6.0... but those methods are provided by libarclite. (You know, the library that gets linked in when you try to deploy ARC code back to iOS 4.3 or Mac OS X 10.6 -- it's not just for ARC anymore!) So all you need to do is declare them in a header, link ARCLite if you're not already, and you're good to go.

这篇关于我是否应该使用文字语法或构造函数来创建字典和数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆