plist、数组和字典的元素之间有啥关系?

Posted

技术标签:

【中文标题】plist、数组和字典的元素之间有啥关系?【英文标题】:What is the relationship between elements of plists, arrays and dictionaries?plist、数组和字典的元素之间有什么关系? 【发布时间】:2013-10-28 23:12:32 【问题描述】:

我有一个简单的程序,需要记录并永久存储用户每次在表格视图中选择项目时生成的 2 条简单数据。这两条数据是1)点击的时间(NSDate)和2)点击的项目名称(NSString)。此时,此信息采用以下形式:

TimerEvent *latestTappedEvent = [[TimerEvent alloc] init];
latestTappedEvent.timeTapped = NSDate.date;
latestTappedEvent.activityTapped = tappedItem.itemName;

这两个数据片段必须保持相互关联。

我的问题是这样的:

如何将这些数据按时间顺序输入和输出 plist?

在我的研究中,我只是变得更加困惑。如何使用 plist 对我来说并不明显。最初,我认为我可以使用NSMutableDictionarylatestTappedEvent.timeTapped 作为键,latestTappedEvent.activityTapped 作为值。但是当我尝试手动构建 plist 时,它似乎是不可能的,而是想要一个字符串作为键。

如果有人能帮助我理解这一点,最好是通过图形表示这些不同元素之间的关系,我将永远感激不尽。

【问题讨论】:

与其将.timeTapped.activityTapped 单独存储到某个集合中,为什么不存储您正在实例化的TimerEvent 对象? 你用的是setValueForKey还是setObjectForKey?他们是不同的...... 【参考方案1】:

字典和数组都存储“事物”——并且通过使用“其他事物”对数据结构进行“查找”来检索和设置存储的事物。在数组中,该查找是存储对象的数组中的索引。表格形式:

Index       Storage

0           "some string stored at index 0"

1           "some other string"

2           <some other object, stored at index 2>

要找到"some string stored at index 0",您需要知道它存储在索引 0 处,并在数组中查询该索引处的对象。所以数组使用整数来查找存储在其中的对象,并且这些整数必须在 0 到数组计数减 1 的范围内。使用整数查找数组中的项目也给出了数组顺序 - 从上到下- 您在上表中看到的底部顺序与代码中迭代产生的顺序相同。

字典使用任意对象进行查找,这也意味着字典中没有排序,只有一组键和它们所指的关联。表格形式:

Key         Storage

"name"      "a string that will be accessed using the key 'name'"

"number"    <some numeric object, that will be accessed using the key 'number'>

<object>    "will be accessed with key <object> which is an arbitrary object"

要从该字典中获取"a string that will be accessed using the key 'name'",您需要向字典询问"name" 键下存储的内容。

在上面的例子中,我给了表标题“索引 - 存储”或“键 - 存储”,但要回到这些结构都存储东西的点,并且可以使用其他东西访问,让我们查看数组更通用的表格:

Thing used to access the thing that's stored        Thing that's stored

0                                                   "some string stored at index 0"

1                                                   "some other string"

2                                                   <some other object, stored at index 2>

再一次,字典,同一张表:

Thing used to access the thing that's stored        Thing that's stored

"name"                                              "a string that will be accessed using the key 'name'"

"number"                                            <some numeric object, that will be accessed using the key 'number'>

<object>                                            "will be accessed with key <object> which is an arbitrary object"

另外,让我们在同一张表中查看您的班级TimerEvent

Thing used to access the thing that's stored                Thing that's stored

timeTapped                                                  <date object>

activityTapped                                              "name of an activity"

左列中的项目是 Objective-C 属性名称,而右列中的项目是这些属性包含的值。现在,再看一下字典——左边的项目是任意值(实际上它们通常是字符串),右边的项目是其他任意值。希望您能在这里看到这种联系——您通常可以将对象的属性表示为一个字典,该字典将属性名称的字符串表示映射到属性存储的值。因此,如果您想在字典中表示 TimerEvent 对象,您最终会得到如下表示:

Key                 Object

"timeTapped"        <date object>

"activityTapped"    "activity name"

上表说明了数组、字典和其他对象之间的共性和差异,并表明使用字典将属性名称映射到属性值可以表示任何给定对象的属性。那么,执行此操作的代码看起来如何?假设我们要在NSDictionary 中表示TimerEvent 对象timerEvent

NSDictionary *timerEventRepresentation = @ @"timeTapped": timerEvent.timeTapped,
                                            @"activityTapped": timerEvent.activityTapped;

下面是我们如何从字典表示创建TimerEvent

TimerEvent *timerEvent = [[TimerEvent alloc] init];
timerEvent.timeTapped = timerEventDictionaryRepresentation[@"timeTapped"];
timerEvent.activityTapped = timerEventDictionaryRepresentation[@"activityTapped"];

将所有对象强制转换为字典的目的是属性列表格式仅序列化几个类 - NSArrayNSDictionaryNSStringNSDateNSNumberNSData。因此,我们编写代码来使用支持的类来表示不支持的类,反之亦然,以在 plist 中序列化这些对象。

作为附录,您提到您需要存储所有点击的记录,并对它们进行排序。正如我上面提到的,数组固有地对它们存储的东西进行排序,所以这是合适的解决方案。你会想要构建一个看起来像这样的东西:

Index        Item
0            <dictionary representing first tap>
1            <dictionary representing second tap>
...
n            <dictionary representing n-1th tap>

在代码中,序列化每个点击将采用与前面所述相同的形式,但请确保添加一个额外的步骤,即在 NSMutableArray 属性上以新创建的字典作为参数调用 addObject:

【讨论】:

非常感谢您详尽详尽的解释,Carl!我现在正在消化并尝试实施。 FWIW,我将使用 NSMutableDictionary,每次用户点击新活动时都会更新它,并且内容将在退出时写入 plist,然后读回以添加更多条目。跨度> @TimJones 不客气。使用NSMutableDictionary,原理是一样的——除了你会做mutableTimerEventRepresentation[@"timeTapped"] = timerEvent.timeTapped; mutableTimerEventRepresention[@"activityTapped] = timerEvent.activityTapped;之类的事情,而不是每次都创建一个新字典。 @Carl--仍然困扰我的是:由于每次点击都会创建一个新的 timerEvent,如果它们都具有相同的标识符,如何区分它们?每个条目的“timeTapped”值是唯一的,但“activityTapped”的值可以(并且将会)变化,因此多个条目可以具有相同的“activityTapped”值。我的观点是,我需要能够根据这两个属性进行检索和排序。 @TimJones 如果您必须存储多个实例,那么您需要多个字典在一个可变数组中,每次点击添加一个新字典 - 而不是可变字典。就像您的对象一次只能为每个属性设置一个值一样,字典一次只能为一个键设置一个值。 @Carl——我得去试试这个。我的右脑天性可能会妨碍理解其他人认为直截了当的概念。再次感谢您的耐心等待!

以上是关于plist、数组和字典的元素之间有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章

Python字典的一点用法

通过数组元素的父子关系形成一个字典类型的树列表

2.3 字典

从数组(plist)中删除字典元素 Cocoa Touch

Python第六课 字典和集合

Python第六课 字典和集合