This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to populate UITableView with plist
I save data to plist like this:
- (IBAction)save:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"data.plist"];
NSMutableArray *data = [NSMutableArray arrayWithContentsOfFile:plistPath];
if (nil == data) {
data = [[NSMutableArray alloc] initWithCapacity:0];
}
else {
[data retain];
}
NSMutableDictionary *array = [[NSMutableDictionary alloc]init];
[array setObject:label1.text forKey:#"Test1"];
[array setObject:label2.text forKey:#"Test2"];
[array setObject:label3.text forKey:#"Test3"];
[array setObject:label4.text forKey:#"Test4"];
NSLog(#"%#", array);
[data addObject:array];
[array release];
[data writeToFile:plistPath atomically: TRUE];
[data release];
}
NSLog:
2012-07-01 18:52:19.566 testapp[22651:707] {
Test1 = 40;
Test2 = 102;
Test3 = 153;
Test4 = 255;
}
How can I load saved data to uitableview?
To read it, do this:
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
You should then be able to read the values for all the keys like this:
NSString *myValue = [plistDict objectForKey:#"someKey"];
edit:
After rereading your code it seems like you might be doing something you don't want to do. Your current plist structure is a top level array that adds a dictionary to itself every time you invoke "save". Is this what you're trying to do? If so, what represents a cell in your table, an index in the array?
If so, then you want to do
// top level array
NSMutableDictionary* plistArray = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
// individual dictionary at one array index (such as indexPath.row in cellForRowAtIndexPath)
NSMutableDictionary *dictionary = [plistArray objectAtIndex:yourIndex];
In any case, the object you have named "array" is actually a dictionary so you should rename it (or change it to be an array if that's what you want).
Related
I am developing iPhone app in which i have TableView,
What i want to do is On click of UITableViewCell i want to remove this values from plist, MOBILES.Brand.2 and MOBILES.Brand.5 if they exist in .plist if they doesn't exist in .plist then i want to add it to my .plist
Here is the structure of my .plist:
:
Here is my code snippet:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
plistPath = [self getPlistPath];
//PlistDict is mutableDictionary contains the keys and values of .plist (of above image)
if ([PlistDict valueForKeyPath:#"MOBILES.Brand.2"] != nil) { //if key and it's value exists in Filter.plist
//Delete Key from .plist...
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
[savedStock removeObjectForKey:#"MOBILES.Brand.2"];
[savedStock removeObjectForKey:#"MOBILES.Brand.5"];
[savedStock writeToFile:plistPath atomically:YES];
}else{
//Add Key to .plist
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
[data setValue:#"251" forKeyPath:#"MOBILES.Brand.2"];
[data setValue:#"298" forKeyPath:#"MOBILES.Brand.5"];
[data writeToFile:plistPath atomically:YES];
}
}
-(NSString*)getPlistPath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Filter.plist"];
PlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
return path;
}
after writing above code snippet it doesn't remove the keys from .plist but it adds the key successfully if not existed.
Where i am doing mistake ? please help and thanks in advance.
The problem is you are trying to remove using the NSMutableDictionary keypath directly using removeObjectForKey that requires the exact key not keypath and you are supplying a keypath. Use the following NSMutableDictionary Category taken from here
#interface NSMutableDictionary (Additions)
- (void)removeObjectForKeyPath: (NSString *)keyPath;
#end
#implementation NSMutableDictionary (Additions)
- (void)removeObjectForKeyPath: (NSString *)keyPath
{
// Separate the key path
NSArray * keyPathElements = [keyPath componentsSeparatedByString:#"."];
// Drop the last element and rejoin the path
NSUInteger numElements = [keyPathElements count];
NSString * keyPathHead = [[keyPathElements subarrayWithRange:(NSRange){0, numElements - 1}] componentsJoinedByString:#"."];
// Get the mutable dictionary represented by the path minus that last element
NSMutableDictionary * tailContainer = [self valueForKeyPath:keyPathHead];
// Remove the object represented by the last element
[tailContainer removeObjectForKey:[keyPathElements lastObject]];
}
#end
It should work for you.
Method - 2
If the above doesn't work, you can do an iteration of your dictionary, and specifically delete the object for the key.. Try
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
NSMutableDictionary *brand=[[savedStock objectForKey:#"MOBILES"] objectForKey:#"Brand"];
[brand removeObjectForKey:#"2"];
[brand removeObjectForKey:#"5"];
Cheers.
I have this plist file
I need to make an array containing the arrays in the plist, so the array should have the values "numbers" & "colors" .
I tried this code but didn't work
- (NSString *) dataFilePath {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
return [documentDirectory stringByAppendingPathComponent:#"groups.plist"];
}
- (void) readPlist {
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:#"Root"];
NSLog(#"%#", tempArray);
}
calling the readPlist from ViewDidLoad Method
any idea how to do it ?
Instead of
NSArray *tempArray = [dict objectForKey:#"Root"];
NSLog(#"%#", tempArray);
use
NSArray *tempArray = [dict allKeys];
NSLog(#"%#", tempArray);
Note that the order of the elements in the array is not defined, see the documentation of NSDictionary,
"Root" is just a label from Xcode.
Ensure that the groups.plist file exists in the Documents Directory and not in your Bundle Directory.
Ensure that the dict is not nil and is actually a dictionary object as you expect.
Have you tried [dict objectForKey:#"numbers"]?
I have an NSMutableArray of NSMutableDictionary (it's a plist). Each dictionary in the array has 2 keys: 'id' and 'lu'.
How can I find the index in NSMutableArray of NSMutableDictionary where, for example, id = '47653'?
I tried to do it but it's not working:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *path = [basePath stringByAppendingPathComponent:#"id.plist"];
NSMutableArray *mut_array = [[NSArray arrayWithContentsOfFile:path] mutableCopy];
NSMutableDictionary *mut_dico = [[NSMutableDictionary alloc] init];
NSString *egalIDPlistData = [contentDictio objectForKey:#"id"];
for(mut_dico in mut_array) {
if([[mut_dico objectForKey:#"id"] isEqualToString:#"47653"]) {
NSLog(#"Test");
}
}
NSMutableArray *mut_array = [[NSArray arrayWithContentsOfFile:path] mutableCopy]; will create a mutable array of immutable dictionaries, not mutable dictionaries. mutableCopy is not a deep copy.
Regardless of mutability, the following will do what you want:
NSUInteger indexOfDictionary = [[array valueForKey:#"id"] indexOfObject:#"49711"];
if(indexOfDictionary == NSNotFound)
{
NSLog(#"no matching objects found!");
return;
}
NSDictionary *fullDictionary = [array objectAtIndex:indexOfObject];
The valueForKey: uses the fact that a key-value coding call on an array returns an array of the results of that call on each object in the array, in the same order, and the fact that NSDictionary will respond similarly in this situation to both valueForKey: and objectForKey:
As for the issue of whether what you're really dealing with is strings or numbers, try using just #49711 in place of #"49711" and if that works instead you've got numbers.
In your log id is 49711 & in your if condition it is 47653. Your condition will not satisfy until there is dictionary in your array with id = 47653
The objects in the loaded plist are not mutable.
Try:
for(NSDictionary * dict in mut_array)
{
if([[dict objectForKey:#"id"] isEqualToString:#"49711"]) {
NSLog(#"Test");
}
}
I am using this code to add content into a plist :
//////////// Save data into plist /////////////////
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"datatesting.plist"];
NSLog(#"path='%#'",path);
NSFileManager *nfm = [[NSFileManager alloc] init];
if([nfm fileExistsAtPath:path])
{
// if file exists, get its contents, add more entries and write back
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSArray *keys = [NSArray arrayWithObjects:#"Title",#"Description",#"Coordinate",nil];
[array addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSString stringWithFormat:#"%#",titlestring],[NSString stringWithFormat:#"%#",descriptionstring],[NSString stringWithFormat:#"%#",coordinadastring], nil] forKeys:keys]];
NSLog(#"modified array=%#",array);
BOOL ok = [array writeToFile:path atomically:YES];
if(!ok){
NSLog(#"Unable to write appended file");
return;
}
} else {
// if file doesn't exist, create a new one
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *keys = [NSArray arrayWithObjects:#"Title",#"Description",#"Coordinate",nil];
[array addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSString stringWithFormat:#"%#",titlestring],[NSString stringWithFormat:#"%#",descriptionstring],[NSString stringWithFormat:#"%#",coordinadastring], nil] forKeys:keys]];
NSLog(#"new array=%#",array);
BOOL ok = [array writeToFile:path atomically:YES];
if(!ok){
NSLog(#"Unable to write new file");
return;
}
}
Now I am having issues in using the content of the plist. So my two questions are :
- What is the Keys of the dictionaries of the current plist ?
- What is the way to read the content in a Tableview ?
You have an array of dictionaries. You need to iterate on the contents of the array, then look at each dictionary. You can do this with block enumerators or the older for() style. I'll use the latter now as you may not know blocks.
NSArray *array = ...; // read in the array from the file
for(NSDictionary *dict in array) {
NSString *title = [dict objectForKey:#"Title"];
... etc
}
When you want to show this data in a tablview, the number of rows is the number of dictionaries (ie [array count]). If you wanted to show just the title for each cell, you would get the cell row number, then get the dictionary by [array objectAtIndex:cellRow]), then pull out the title as above.
Can I read just the key from plist without its value, also if I know the value can I read the key ?
Reading .plist:
NSString *path = [[NSBundle mainBundle] pathForResource:#"myPlist" ofType:#"plist"];
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
Getting all keys and all values:
NSArray* allmyKeys = [myDictionary allKeys];
NSArray* allmyValues= [myDictionary allValues];
Getting all keys for an values object:
NSArray* allmyKeys = [myDictionary allKeysForObject:myValueObject];
As an alternative, you can use allKeysForObject: method which returns,
A new array containing the keys corresponding to all occurrences of anObject in the dictionary. If no object matching anObject is found, returns an empty array.
From that array you can get the key by invoking the objectAtIndex: method.
Use -[NSDictionary allKeysForObject:]*.
Example
NSArray *keys = [myDict allKeysForObject:#"My Value"];
if ([keys count] != 0) { // to prevent out-of-bounds crashes
NSString *key = [keys objectAtIndex:0];
return key;
} else {
return nil;
}
*Dunno why it returns an NSArray object instead of an NSSet object, because keys are not ordered. Oh well.
In order to read the values at app's installed folder:
NSString *PListName=#"ExamplePlist";
NSString *_PlistNameWithExtension=[NSString stringWithFormat:#"%#.plist",PlistName];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:_PlistNameWithExtension]; //3
NSDictionary *myDictionary = [[NSDictionary alloc] initWithContentsOfFile:path];
NSLog(#"%#",[myDictionary description]);
NSArray *AllKeys=[myDictionary allKeys];
Jhaliya's method has not worked for me, then I tried this method.