Best way to store table view elements? - ios

I have a hierarchy like so -> Days (Table) -> Time (Table) -> Info (View).
Would it be better to store the information as a NSDictionary, with the Days as the keys and the Time as an NSArray for each key, or the Days as NSArray, with another NSArray for Time?
Key things to note:
I'd like the sort the days and Time.
I would be able to delete some Time data within the NSArray if I wanted to.

If you are going to delete or replace elements in an array you must use the mutable versions, NSMutableArray and NSMutableDictionary. I would probably use an array for this purpose.

I would use an NSMutableDictionary of days with an NSMutableArray of times for each day. That way you avoid trying to keep two separate arrays in sync since each "day" key will always point to your array of times.
You can sort your array of times any way you want since it's an array, and you can choose how to show your days in the table simply based on the key. You can access an array of all your keys using the [dictionary allKeys] method.
For example, in viewDidLoad you can use the [dictionary allKeys] method to get an array of the keys of your dictionary. You can sort this whichever way you like, and then iterate through the array in the cellForRowAtIndexPath tableview datasource method.
-(void)viewDidLoad {
/* keys = NSMutableArray instance variable
dictionary = the dictionary of days, with each days value being an array of times
*/
keys = [dictionary allKeys];
//sort however you want
}
And then in your didSelectRowAtIndexPath delegate method, you know which key they selected based on the indexPath.row of the selection and the row of your keys array.

Related

What is the correct way to modify NSDictionary items within an NSMutableArray while enumerating?

Here is a snippet of code that enumerates through NSMutableArray *myArray and modifies each NSMutableDictionary within it. The problem I see with this code is that it's modifying while enumerating.
Code:
for (NSMutableDictionary *aDict in myArray)
{
theDate = [self convertTheDate:[aDict valueForKey:#"date"]];
[aDict setValue:theDate forKey:#"date"];
}
[self passUpdatedDates:myArray];
How should I modify this to be safe code?
Your code should be fine (with the change to setObject:forKey: as Maddy described in his comment), as long as your array myArray really is an array of mutable dictionaries. If any of the dictionaries in the array are not mutable then this code will crash when you try to change the dictionary.
If that's the case then you will need to create a mutable copy of each dictionary, change the key in question, and then save the modified dictionary to the correct index in the array. To do THAT, you now have to deal with modifying an array as you are enumerating it.
The simple way to do this is to change from fast enumeration (for... in) to a for loop that counts through all the indexes and uses objectAtIndex to fetch each object, change it, and save it back to the array.
To continue to use fast enumeration, you can create a new mutable array that is the same size as myArray, loop through myArray with for... insyntax, and simply add each modified dictionary to the new mutable array. Then you are enumerating the source array with fast enumeration and creating a duplicate object in a separate array. This doubles your memory footprint but gives you the performance benefit of fast enumeration.

NSArray vs NSDictionary - Which is better for string searching

I am going to store a list of values in a plist and retrieve them. The list will be searched for a value (which may change each time) each time the search method is called. There will probably be about 10 values in the list.
Is either NSArray or NSDictionary better for a search?
I think that NSArray is more appropriate because right now, at least, I don't have a key-value pair data set, just a list.
Could someone confirm and perhaps offer the best method for search the array?
Thanks
The problem is conceptual:
If you have a list of value, you mustn't use NSDictionary. The appropriate data structure is NSArray or NSSet.
Basically, NSSet is faster than NSArray, because doesn't have to consider the order etc.
So if you need just to search a value and the order doesn't matter, the best data structure to use is NSSet (or NSMutableSet if you need it mutable).
Dictionaries will be faster for searching than arrays because the keys are hashed. With an array the system has to check all the items until it finds a match.
The docs for NSSet say that sets are faster in testing for membership than arrays. If you don't have values to store for each key, the best option might be to store the data to your plist as an array. At runtime, read the array, and load it's contents into a set using the NSSet class method setWithArray:
If your data sets are large (many thousands of items) I would suggest doing performance testing with dictionaries where all the values are NSNull against an NSSet. (With a dictionary you'd use objectForKey: and with a set you'd use the containsObject: method
Ignoring timing the best option would be to use an NSArray. NSArray has all sorts of useful methods such as
(NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate
and
(NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
that you can use for searching within an array.

Need to loop through an array that is inside of another array

I have an array that contains 2 objects. In order to store it on my backend server service, I need to store it inside of another array.
So later on, when I call my server and tell it I want the array object, it sends me a new array object that is holding my original array object.
I need to loop through the new array (that contains my original array), and then loop through all of the objects inside of my original array.
I know how to do a normal for loop and loop through an array, but I have never had to do it like this where you need to loop through an array that is contained inside of another array.
I have been thinking about ways to do this now for about an hour and really have no clue. I think what I need to do is technically called "looping through nested arrays" but I can't seem to find anything about doing this with objective-c.
Thanks for the help.
Use a nested for loop and you can iterate through the objects in both arrays:
for(NSArray* array in arrays){
for(object* thing in array){
//do what you want with thing in arrays
}
}
Do you need to loop through every object in both arrays, or do you need to fetch the object from the outer array and just loop through that?
If you need to loop through all objects in both arrays, #JMarsh 's code will do that.
If you only need to fetch the inner array, then just use an explicit fetch Following JMarsh's format:
NSArray *innerArray = arrays[1]; //Or whatever array index is correct
for(id thing in innerArray)
{
//do what you want with thing
}

Data representation suited for UITableViewDataSource

Currently, I have the following set up in my app:
For example, I have a gamelist, where the games have different states and I would like a certain state to be in a certain section etc.
Since I have 3 different states I'll use a NSDictionary with State as key and Array as value and put a certain game with a certain state in the correct array.
Then my code for numberOfRowsInSection would be something like:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString* state = [self getStateForSection:section];
return [[obj objectForKey:state] count];
}
The problem is I dislike having the objects in arrays since then I have to look through the whole array whenever I want to access a certain match.
I would instead like to have all matches in a single NSDictionary with matchID as key and NSDictionary with as value (the match).
But how would I do in UITableView then?
I could do something where I return allKeys of my NSDictionary but I still have to iterate it to find their current state and add their key to the appropriate list?
You could just also build a NSDictionary from matchID to match on the side as well, simply reusing the same objects and keeping the NSDictionary of NSArrays just for the table data source. Then the problem is that you have to update both when the data changes. You may also want to look into NSArray filteredArrayUsingPredicate:
Another possibility is using another data structure known as the sorted dictionary which keeps its keys in a specific order. That way you can ask for all the values as an array for the table view and get a constant order, but still be able to do a lookup with a matchID directly to a match.

Loading NSDictionary from Plist as Listed

I'm using plist to store key-value lists. When the application needs that list, trying load list to a NSDictionary. Everything is well until here.
Here how I load the plist file:
NSString *myPlistFilePath = [[NSBundle mainBundle] pathForResource: #"cities" ofType: #"plist"];
cities = [NSDictionary dictionaryWithContentsOfFile: myPlistFilePath];
When we look at, cities is a NSDictionary. Then I pushed all list key values to a TableView, somehow its not listed as in plist file. Sorting random.
Is there way to figure out?
Thanks in advance.
An NSDictionary is not an ordered collection, that is, it does not guarantee to preserve order of the contents in any way. Its only function is to map from keys to values.
If you need the contents ordered, you can extract it from the NSDictionary using for example keysSortedByValueUsingSelector, which will extract the data in the collection, sort it by your criteria and store it in an (order preserving) NSArray.
Alternatively, consider using an Array in the root of the plist, containing an ordered list of city dictionaries. Then if you iterate over the array contained therein, they will be in the array order contained in the plist.
NSDictionary is not an ordered data structure.
Objects are listed based on allKeys functions and keys are listed in undefined way.
See the apple doc for allKeys function.
allKeys Returns a new array containing the dictionary’s keys.
(NSArray *)allKeys
Return Value A new array containing the dictionary’s keys, or an empty
array if the dictionary has no entries.
Discussion The order of the elements in the array is not defined.
If you wish to avoid using a selector to sort the keys, consider using an Array in the root of the plist. Then when you iterate over the array, the order is preserved. This runs o(n), which is shorter than the fastest possible sort algorithm by a factor of log(n)
eg:
cities{
list[
city{}
city{}
city{}
...
]
}

Resources