Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the relationship between elements of plists, arrays and dictionaries?

I've got a simple program that needs to log and persistently store 2 simple pieces of data produced each time the user selects an item in a table view. The two pieces of data are 1) the time of the tap (NSDate) and 2) the name of the item tapped (NSString). At this point, this information is in this form:

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

The two data pieces must remain associated with each other.

My question is this:

How do I get this data into and out of a plist, ordered chronologically?

In my research, I have only become more confused. It's just not obvious to me how to use a plist. Initially, I thought I could use an NSMutableDictionary with latestTappedEvent.timeTapped as a key, and latestTappedEvent.activityTapped as the value. But when I tried to construct the plist manually, it appears not to be possible, wanting instead a string for a key.

If anyone can help me understand this, preferably by giving a graphic representation of the relationship among these different elements, I would be forever grateful.

like image 456
rattletrap99 Avatar asked Nov 02 '22 11:11

rattletrap99


1 Answers

Dictionaries and arrays both store 'things' - and the things stored are retrieved and set by using 'something else' to do a 'lookup' on the data structure. In an array, that lookup is the index in the array where an object is stored. In tabular form:

Index       Storage

0           "some string stored at index 0"

1           "some other string"

2           <some other object, stored at index 2>

To find "some string stored at index 0" you would need to know it's stored at index 0 and ask the array for the object at that index. So arrays use integers to look up objects stored in them, and these integers must be in the range of 0 to the array's count minus 1. The use of integers to look up items in the array also gives the array order - the top-to-bottom ordering you see in the table above is the same order that iterating in code would yield.

Dictionaries use arbitrary objects to do the lookup which also means there's no ordering in a dictionary, there's just a set of associations of keys and what they refer to. In tabular form:

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"

To get "a string that will be accessed using the key 'name'" from this dictionary, you ask the dictionary for what's stored under the key "name".

In the above examples, I gave the table heading "Index - Storage" or "Key - Storage", but to circle back to the point that these structures both store things hat are accessed using another thing, let's view the array with a more generic table:

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>

And again, the dictionary, with the same table:

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"

Also, let's view your class TimerEvent in the same table:

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

timeTapped                                                  <date object>

activityTapped                                              "name of an activity"

The items in the left column are Objective-C property names, and the items on the right are the values those properties contain. Now, take another look at the dictionary - the items on the left are arbitrary values (in practice they are commonly strings) and the items on the right are other arbitrary values. Hopefully you can see the connection here - that you can generally represent an object's properties as a dictionary that maps the string representation of a property name to the value the property stores. So, if you want to represent the TimerEvent object in a dictionary, you'd end up with a representation like:

Key                 Object

"timeTapped"        <date object>

"activityTapped"    "activity name"

The tables above illustrate the commonalities and differences between arrays, dictionaries, and other objects, and show that using a dictionary to map property names to property values can represent the properties of any given object. So, how would the code to do this look? Let's say we want to represent the TimerEvent object timerEvent in an NSDictionary:

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

And here's how we could create a TimerEvent from a dictionary representation:

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

The purpose behind coercing all your objects into dictionaries is that the property list format only serializes a few classes - NSArray, NSDictionary, NSString, NSDate, NSNumber, and NSData. So we write code to represent non-supported classes using the supported ones, and vice versa, to serialize these objects in plists.

As an addendum, you mention that you need to store a record of all taps, and sort them. As I mentioned above, arrays inherently order the things they store, so that is the appropriate solution here. You'd want to build something that looked like this:

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

In code, serializing each tap would take the same form as was described earlier, but make sure to add an extra step of calling addObject: on an NSMutableArray property with the newly-created dictionary as the parameter.

like image 175
Carl Veazey Avatar answered Nov 12 '22 19:11

Carl Veazey