Reading a plist dictionary - uitableview

I am stuck trying to figure out how this works. I have a plist that is an array of dictionaries. I need to read each dictionary separately within the array and map each dictionary to cells in a tableview. I have a feeling this is extremely simple, but I am not having success accessing the first dictionary and writing each key/value pair to a tableview; then in response to 'next' button, writing 2nd dictionary to tavbeview, then 3rd dictionary, etc. etc. I don't have to go backward, but I do have to go forward displaying contents of each successive dictionary in tableview.
Any tips/code samples will to be much appreciated.

Is this what you mean?
NSDictionary *cellValue = [self.array objectAtIndex:[indexPath row]];
NSString *label = [cellValue objectForKey:#"label"];
[cell.textLabel setText:label];
The array is initialized with the contents of an plist. The plist has a dictionary with a key called label which can then be accessed through objectForKey.
I am not exactly sure what you are doing for writing your dictionaries, but what I did was create a custom class called DataObject added I few methods like addNewItem and writeToFile like this:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:fileTitle];
[array writeToFile:finalPath atomically:YES];
and for addNewItem:(NSString *)label:
NSDictionary *newItem = [[NSDictionary alloc] initWithObjectsAndKeys:label,#"label", nil];
[array addObject:newItem];
[newItem release];
[self writeTask];
Then simply access them like this:
DataObject *db = [[DataObject alloc] init];
[db addNewItem:youItemTitle];
[db release];
although this would be very bad for memory management.

Related

Parsing csv file to NSMutableArray

I know the instructions are all over of how to read a .csv file in objective c then pass it to an NSMuatbleArray, but I'm getting problems when I assign it to a mutableArray. I've spent hours of checking online and trying to fix it, but nothing helped.
Here is my objective c code:
NSError *err;
NSString *filePath = [NSString stringWithContentsOfFile:#"/users/Mike/Desktop/Book1.csv" encoding:NSUTF8StringEncoding error:&err];
NSString *replace = [filePath stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSString *something = [replace stringByReplacingOccurrencesOfString:#"," withString:#"\n"];
NSMutableArray *columns = [[NSMutableArray alloc] initWithObjects:[something componentsSeparatedByString:#"\n"], nil];
NSLog(#"%#", filePath);
NSLog(#"%#", something);
NSLog(#"%#", columns);
Here is the output:
My App[1854:54976] Kitchen,Bathroom,Dinning Room,Living Room
My App[1854:54976] Kitchen
Bathroom
Dinning Room
Living Room
My App[1854:54976] (
(
Kitchen,
Bathroom,
"Dinning Room",
"Living Room"
)
)
The problem is that the output of the array comes with commas and quotations which I eliminated.
What I need is for the array "columns" to come out like the string "something".
Update
I took away the two strings of "replace" and "something" and switched the array to:
collumns = [[NSMutableArray alloc] initWithObjects:[filePath componentsSeparatedByString:#","], nil];
Now I'm having trouble loading it to a table view. Here's my code for that.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"firstCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [columns objectAtIndex:indexPath.row];
return cell;
}
The app just crashes with an unexplaned reason, but when I make another array manually, it works.
This one works:
NSMutableArrayrow = [[NSMutableArray alloc] initWithObjects:#"First", #"Second", nil];
Your code is a bit muddled, and contains one error that is the cause of your unexplained parenthesis.
Why replace quotes with nothing when there are no quotes in the
source data?
Why replace commas with line breaks, and then split the string into
an array of strings on the line breaks (which gets rid of the line
breaks entirely)? Why not just split the string into an array using
commas and skip the intermediate step?
Finally, and most seriously, the method initWithObjects wants a
comma-delimited set of objects, then a nil. You are passing it an
array, and nil. So what you are getting as a result is a mutable
array that contains a single object, an immutable array. This is
almost certainly not what you want.
This line:
NSMutableArray *columns =
[[NSMutableArray alloc] initWithObjects:
[something componentsSeparatedByString:#"\n"], nil];
...is wrong.
You would use initWithObjects like this:
NSMutableArray *columns =
[[NSMutableArray alloc] initWithObjects: #"one", #"two", #"three", nil];
Note how I'm passing in a comma-separated list of objects, and then a nil. Your use of initWithObjects is passing in a single object, an array, and then a nil. You won't get a mutable array that contains the objects from the source array - you'll get a mutable array that contains your starting immutable array.
It should be written like this instead:
NSMutableArray *columns = [[something componentsSeparatedByString:#"\n"]
mutableCopy];
Or better yet, do it in 2 steps so it's clear whats going on:
NSArray *tempArray = [something componentsSeparatedByString:#"\n"];
NSMutableArray *columns = [tempArray mutableCopy];

Do NSArrays stay sorted when saved then retrieved from a plist

Simple question do NSArrays stay sorted when saved to a plist and then retrieved?
I am having a sorting issue when i retrieve my array from my plist so i was curious.
I think it may also be a problem with this line. Do these maintain the order from titles followed the order of titleArr?
NSMutableArray *allTitles = [[NSMutableArray alloc] init];
[allTitles addObjectsFromArray:titles];
[allTitles addObjectsFromArray:titleArr];
How I save to plist
imageInfo = [[NSMutableArray array] init];
NSMutableArray *Listing = [NSMutableArray array];
[imageInfo addObject:Listing];
NSDictionary *Images = [NSDictionary dictionaryWithObjectsAndKeys:
allTitles, kKeyTitle,
allMediaUrls, kKeyThumbUrl,
allWidths, kKeyThumbWidth,
allHeights, kKeyThumbHeight,
nil];
[Listing addObject:Images];
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask, YES);
NSString *documentsDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"image.plist"];
NSLog(#"Plist File Path: %#", filePath);
BOOL didWriteToFile = [imageInfo writeToFile:filePath atomically:YES];
if (didWriteToFile) {
NSLog(#"Write to .plist file is a SUCCESS!");
} else {
NSLog(#"Write to .plist file is a FAILURE!");
}
Yes if titles and titleArr are sorted than allTitles will also be sorted.
First all objects of titles will be added and than at all objects titleArr will be added as addObjectsFromArray method starts adding object array towards the end of receiving array.
Here is more info from Apple Docs
Adds the objects contained in another given array to the end of the
receiving array’s content.
So yes plist will have sorted array.
Severe bug:
imageInfo = [[NSMutableArray array] init];
[NSMutableArray array] returns an initialised and autoreleased array.
Sending an init message to that array is not a good idea.

NSDictionary allKeysForObject in an array

I have a NSDictonary that looks like this. I need to get all the key values that are associated for a particular name. For example the name Samrin is associated with keys 11.titleKey, 110.titleKey and so on. The problem I have is that I am not sure how can I get to the object in an array and then pass they key value back?
I tried the following code with not much success.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"birthdays.plist"];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:stringsPlistPath];
NSArray *temp = [dictionary allKeysForObject:#"Samrin Ateequi"];
NSLog(#"temp: %# ...", temp);
OUTPUT:
temp: (
) ...
I think you can use keysOfEntriesPassingTest for that. Something like:
NSSet *keysSet = [dictionary keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
if ([[obj objectAtIndex:0] isEqualToString:#"Samrin Ateequi"]) {
return YES;
} else {
return NO;
}
}];
allKeysForObject: looks through the dictionary for values equal to that object using isEqual:. Your values for that dictionary are NSArrays, so it will never match the NSString you are looking for.
If you don't change the data structure you will have to loop through everything to get the results you need.
If you are willing to upgrade to Core Data with an SQL store, then your results will be fast and the code will be easier than looping through the dictionary. This is the kind of problem that Core Data was meant to solve. You can get started with the Core Data Programming Guide.
Hope this will help you: I have taken an example.
NSDictionary *dict = #{#"key1":#[#"mania",#"champ"],
#"key2":#[#"mann",#"champ"],
#"key3":#[#"mania",#"champ",#"temp"]};
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"ANY SELF=%#",#"mania"];
NSArray *allValues = [dict allValues];
NSArray *requiredRows = [allValues filteredArrayUsingPredicate:filterPredicate];
NSMutableArray *requiredKeyArray = [[NSMutableArray alloc]initWithCapacity:0];
for (id anObj in requiredRows) {
[requiredKeyArray addObject:[dict allKeysForObject:anObj]];
}
NSLog(#"Desc: %#",[requiredKeyArray description]);

NSDictionary valueForKey crash

How can i retrieve the key value from the below NSMutableArray array. The below code crashes on isEqualToString. However i can see the value of nsRet in the variable view window as #\x18\xaa\x01\xc8\a before running that statement.
NSMutableArray* nsMyList = [[NSMutableArray alloc] init];
[nsMyList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"valueOfKey", #"Key",
nil]];
NSString *nsRet = [nsMyList valueForKey:#"Key"];
if ([nsRet isEqualToString:#"deviceClass"])
{
NSLog(#"Key value:%#", nsRet);
}
Can anyone here please help me get the correct value for the key?
Thanks.
This is because you need objectForKey:, not valueForKey:. The valueForKey: method is for key-value programming. Moreover, the call should be on the [nsMyList objectAtIndex:0], like this:
NSString *nsRet = [[nsMyList objectAtIndex:0] objectForKey:#"Key"]
You've stored the NSDictionary in an array. The correct access based on your code would be:
NSDictionary *dict = [nsMyList objectAtIndex:0];
nsret = [dict valueForKey:#"Key"];
It looks like you are trying to get the valueForKey: on an NSMutableArray rather than on the dictionary.
What you want is:
[[nsMyList objectAtIndex:0] valueForKey:#"Key"];
I am a bit lost.
In order to access the dictionary you just create you need to obtain the first element in the NSMutableArray and then the dictionary.
It will be something like this:
NSString *nsRet = [nsMyList[0] objectForKey:#"Key"]
I think it can solve it.

Sort NSDictionary by value within an inner nested NSDictionary

I'm working on a language learning app. So I have an NSMutableDictionary with 'word' as keys. The objects for these keys are nested NSDictionaries with the keys 'frequency' and 'count'. NSNumbers are the objects for 'frequency' and 'count'.
Here is the initializing code:
NSString* path = [[NSBundle mainBundle] pathForResource:#"french_top_50000"
ofType:#"txt"];
NSString *fh = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
self.userWordlist = [[NSMutableDictionary alloc] init];
for (NSString *word in fh) {
NSArray *keyArray = [[NSArray alloc] initWithObjects:#"frequency", #"count", nil];
NSArray *objectArray = [[NSArray alloc] initWithObjects:frequency, count, nil];
NSDictionary *detailsDict = [[NSDictionary alloc] initWithObjects:objectArray forKeys:keyArray];
[self.userWordlist setObject:detailsDict forKey:word];
}
I'm displaying part of this list in a table, and I want to sort by 'frequency', one of the inner keys. I can't figure out how to do this.
In case the first thought is, "Why did you store this in a nested dictionary?", I wanted the words to be keys because in other parts of the app I frequently search to see if a word is in the NSMutableDictionary.
I thought about having a flat dictionary with the following keys:
'word','frequency','count'
... but I'd have to enumerate to check for inclusion of words.
If there are any suggestions for a better data structure strategy I'd love to hear them. I'm going to be checking very frequently for inclusion of 'words' and less frequently will be sorting based on 'frequency' or 'count'.
I've seen lots of question similar to this but they're all for flat dictionaries.
If I understand correctly, use keysSortedByValueUsingComparator: like this:
NSArray *keysByFrequency = [self.userWordlist keysSortedByValueUsingComparator:^NSComparisonResult(NSDictionary* obj1, NSDictionary* obj2) {
return [obj1[#"frequency"] compare:obj2[#"frequency"]];
}];
Then you can iterate keys sorted by their frequency
for (NSString *word in keysByFrequency){
NSDictionary *detailsDict = self.userWordList[word];
// Do whatever...
}

Resources