how to add multiple Array in PList - iphone

I have a for loop on that for loop I have to store Multiple Array in Plist. But my values are getting overlapped and multiple arrays are not been creating .. what I am doing is
for (i=0;i<10;i++) {
plistDict=[NSMutableDictionary dictionaryWithContentsOfFile:filePath];
[plistDict setObject:#"a" forKey:#"b"];
[plistDict writeToFile:filePath atomically:YES];
}
This code wont create multiple Array. This will store only once but I need the multiple times array to be created. And every time it should store object and key. What should I do ?

In above code every time your replace old dictionary with new one. This is the reason you have only on dictionary at end of for loop.
try this
NSMutableArray *arr = [NSMutableArray alloc]init];
for (i=0;i<10;i++)
{
plistDict=[NSMutableDictionary dictionaryWithContentsOfFile:filePath];
[plistDict setObject:#"a" forKey:#"b"];
[arr addObject:plistDict];
}
[arr writeToFile:filePath atomically:YES];}

Try this one.
plistDict=[NSMutableDictionary dictionaryWithContentsOfFile:filePath];
for (i=0;i<10;i++)
{
NSMutableArray *array=[[NSMutableArray alloc] initWithObjects:#"1",#"2",#"3", nil];
[plistDict setObject:array forKey:[NSString stringWithFormat:#"%d",i]];
}
[plistDict writeToFile:filePath atomically:YES];

Related

NSMutableArray objectAtIndex: Not Working

I am new to ios development. I am getting certain data from my web services in the form of Dictionary(Which contains a variable and an array of item dictionaries). I am successfully able to store data in userdefaults.
I form a new array named img_urls for a specific key from each item dictionary using for loop.
My problem is: when i access this array using [ img_urls objectAtIndex:0] , i get complete array as output rather than getting value only at 0th index. And giving [img_urls objectAtIndex:1] gives me NSRangeException.
Here is my code:
NSDictionary *restData=[[NSUserDefaults standardUserDefaults]valueForKey:#"Rest data"];
totalResult=[[restData valueForKey:#"totalResult"]intValue];
restaurants=[[NSArray alloc] initWithObjects:[restData valueForKey:#"restaurants"], nil ];
for(NSDictionary *item in restaurants)
{
[img_urls addObject:[item valueForKey:#"profileImage"]];
}
NSLog(#"REST NAMES%#",[img_urls objectAtIndex:0]);
Any help would be appreciated. Thanks in advance!
Change the method like this below:-
[[NSArray alloc] initWithObjects:[restData valueForKey:#"restaurants"], nil ]to
//Modified below
[[NSArray alloc] initWithArray:[restData valueForKey:#"restaurants"]]
First thing, Did you have analyzed an array, Try like this below:-
img_urls=[NSMutableArray array];
NSDictionary *restData=[[NSUserDefaults standardUserDefaults]valueForKey:#"Rest data"];
totalResult=[[restData valueForKey:#"totalResult"]intValue];
restaurants=[[NSArray alloc] initWithObjects:[restData valueForKey:#"restaurants"], nil ];
for(NSDictionary *item in restaurants)
{
[img_urls addObject:[item valueForKey:#"profileImage"]];
}
//Check first array count
if ([img_urls count] > 0)
{
NSLog(#"REST NAMES%#",[img_urls objectAtIndex:0]);
}
You are giving array([restData valueForKey:#"restaurants"]) as a object to restaurants array while initializing so you will get the whole array when getting by using objectAtIndex:0
NSDictionary *restData=[[NSUserDefaults standardUserDefaults]valueForKey:#"Rest data"];
totalResult=[[restData valueForKey:#"totalResult"]intValue];
restaurants=[[NSArray alloc] initWithArray:[restData valueForKey:#"restaurants"]];
for(NSDictionary *item in restaurants)
{
[img_urls addObject:[item valueForKey:#"profileImage"]];
}
NSLog(#"REST NAMES%#",[img_urls objectAtIndex:0]);

Values are overwrite while saving in NSMutableArray

i am saving the user info in the NSMutableDictionary with key "username" and then saving this Dictionary in another NSMutableDictionary with key "name" and then saving the Dictionary in the NSMutableArray. But the Problem is that whenever i save another user with different username it overwrites the values in the NSMutableArray. Below is the code which i am using
-(void) saveUserData:(NSString *)username
{
NSLog(#"\nsaveDataBarButtonTapped \n");
NSLog(#"the count is %d",[[[ArraysManager sharedInstance] getTotalUserArray] count]);
NSLog(#"ArraysManager description is %# ",[[[ArraysManager sharedInstance] getTotalUserArray] description]);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex:0];
NSString *userArrayFilePath = [[NSString alloc] initWithString:[directory stringByAppendingPathComponent:#"userData"]];
if (username.length != 0)
{
[dataDictionary setObject:[NSString stringWithFormat:#"%#",username] forKey:#"username"];
[dataDictionary setObject:[NSString stringWithFormat:#"%lf",totalValue] forKey:#"totalValue"];
[dataDictionary setObject:[NSString stringWithFormat:#"%lf",totalPayable] forKey:#"totalPayable"];
[userDictionary setObject:dataDictionary forKey:#"userDictionary"];
[[[ArraysManager sharedInstance] getTotalUserArray] addObject:userDictionary];
[[[ArraysManager sharedInstance] getTotalUserArray] writeToFile:userArrayFilePath atomically:NO];
[dataDictionary removeAllObjects];
[userDictionary removeAllObjects];
NSLog(#"ArraysManager description is %# ",[[[ArraysManager sharedInstance] getTotalUserArray] description]);
}
else
{
UIAlertView *noNameAlertView = [[UIAlertView alloc] initWithTitle:#"No Name Found"
message:#"Please Enter the User Name"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[noNameAlertView show];
[noNameAlertView release];
}
}
I think you should write:
[userDictionary setObject:dataDictionary forKey:username];
(Actually I don't understand why you do;
[[[ArraysManager sharedInstance] getTotalUserArray] addObject:userDictionary];
it seems like you are adding the same dictionary each time.)
I think you save with the same key on both occasions so it access the same array, you need to change the key for different dictionaries.
EDIT:
[userDictionary setObject:dataDictionary forKey:[NSString stringWithFormat:#"name%d,nameCount"]];
[dataDictionary removeAllObjects];
[userDictionary removeAllObjects];
I think both the above objects are member variables and you are reusing those member variables to add data to your array. Removing objects from dictionary will not create a new dictionary object but are getting updated in same memory location. Your array will have multiple dictionaries and sub-dictionaries but all are having 2 objects of these all at same memory location.
Instead of these member variables, use these as local variables.
Initialize them in this method and add them to array.
Later release them before end of this method.
Hope it helps
You are doing addObject with the same NSMutableDictionary object.
Did you check the count property after addObject?
For quick fix, just copy the dictionary before add it to the array.
[[[ArraysManager sharedInstance] getTotalUserArray] addObject:[[userDictionary copy] autorelease];
(autorelease for non-ARC configuration)

How to dissect and reorganize info in an NSDictionary

So I have an array of NSDictionaries, each NSDictionary has a bunch of key/value pairs pertaining to aspects of a photo (from Flickr).
I'm making an app that has a UITableViewController whose cells should be each of the different categories of the photos. So in pseudocode, I'm trying to construct a new NSDictionary (with keys being categories of photos, values being the NSDictionaries of the photos that contains that key). I'm iterating through each NSDictionary in the initial array, getting the category tags, and saying, if my new NSDict doesn't contain this key, make a new key to an empty array. Then add the current NSDict to that array. I'm getting consistent errors, not sure why.
Here's the diluted code.
photoList = [FlickrFetcher photosWithTags:[NSArray arrayWithObjects: #"CS193p_SPoT", nil]];
NSLog(#"%#", photoList);
categories = [[NSDictionary alloc] init];
NSArray *temp = [[NSArray alloc] init];
for (id obj in photoList) {
temp = [[obj objectForKey:#"tags"] componentsSeparatedByString:#" "];
for (id string in temp) {
if (![categories objectForKey:string]) {
NSMutableArray *arr = [[NSMutableArray alloc] init];
[categories setObject:arr forKey:string];
//[arr release];
}
NSMutableArray *photos = [categories objectForKey:string];
[photos addObject:obj];
[categories setObject:photos forKey:string];
}
}
Thanks!
NSDictionary doesn't have a method setObject:forKey:. You need an NSMutableDictionary.
self.categories = [NSMutableDictionary dictionary];
Other than that, please do use Joost's excellent rewrite of your code.
SIGABRT, just so you know, most likely means that an assertion somewhere failed. In this case, it may be an assertion all the way down in CoreFoundation*; CF checks for mutability when you try to access a dictionary like that and causes an interrupt if the object isn't mutable.
*I have just learned about the CF source's availability recently and have been looking through it, so this may be just "new thing" bias and incorrect.
I don't notice any errors (syntax-errors, that is) in your code, however here is an updated piece of code which has been implemented a bit cleaner (and without memory leaks)
self.photoList = [FlickrFetcher photosWithTags:[NSArray arrayWithObjects: #"CS193p_SPoT", nil]];
NSLog(#"%#", photoList);
self.categories = [NSDictionary dictionary];
for (NSDictionary *obj in photoList) {
NSArray *temp = [[obj objectForKey:#"tags"] componentsSeparatedByString:#" "];
for (NSString *string in temp) {
NSMutableArray *photos = [categories objectForKey:string];
if (!photos) {
photos = [NSMutableArray array];
[categories setObject:photos forKey:string];
}
[photos addObject:obj];
}
}
If it's not working please tell us the exact warning, and were it is caused.

Replace a value in NSDictionary in iPhone

I have a array (dataArray) of NSDictionary "item". It has datas like "david" for key "name" and "85" for key "marks" etc for 5 students. I want to replace the mark of david to 90 with respect to the array index value (ie 0 for dictionary containing david and 85). How can I do it?
The code for content in array is
[item setobject:name forkey:#"Name"];
[item setobject:mark forkey:#"Marks"];
[dataArray addOject:item]
The above code goes inside parsing, so i have array with 5 objects (students), their name and marks, now I want to replace the mark of the first object in the dataArray.
Here's what you can do:
NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
NSDictionary *oldDict = (NSDictionary *)[dataArray objectAtIndex:0];
[newDict addEntriesFromDictionary:oldDict];
[newDict setObject:#"Don" forKey:#"Name"];
[dataArray replaceObjectAtIndex:0 withObject:newDict];
[newDict release];
Hope this helps!
You first need an NSMutableDictionary with it you can change the key and value.
It would be like this:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"david", #"name", "85", #"marks", nil];
[dict setObject:#"90" forKey:#"david"];
// NSDictionary *dict = ...
NSMutableDictionary *mutableDict = [dict mutableCopy];
[mutableDict setObject:#"myObject" forKey:#"myKey"];
dict = [mutableDict mutableCopy];
I hope it helps
If you want to update an object in a NSDictionary you should use NSMutableDictionary instead.
NSMutableDictionary has the following EXTRA methods
Adding Entries
setObject:forKey:
setValue:forKey:
addEntriesFromDictionary:
setDictionary:
Removing Entries
removeObjectForKey:
removeAllObjects
removeObjectsForKeys:
[davidsRecord setObject:#"100" forkey:#"mark"];

Releasing NSArray containing NSDictionary objects

I am having difficulty getting my head around memory management in the following segment of code on iPhone SDK 3.1.
// Create array to hold each PersonClass object created below
NSMutableArray *arrayToReturn = [[[NSMutableArray alloc] init] autorelease];
NSArray *arrayOfDictionaries = [self generateDictionaryOfPeople];
[arrayOfDictionaries retain];
for (NSDictionary *dictionary in arrayOfDictionaries) {
PersonClass *aPerson = [[PersonClass alloc] init];
for (NSString *key in [dictionary keyEnumerator]) {
if ([key isEqualToString:[[NSString alloc] initWithString: #"FIRST_NAME"]])
aPerson.firstName = [dictionary objectForKey:key];
else if ([key isEqualToString:[[NSString alloc] initWithString: #"LAST_NAME"]])
aPerson.lastName = [dictionary objectForKey:key];
}
// Add the PersonClass object to the arrayToReturn array
[arrayToReturn addObject: aPerson];
// Release the PersonClass object
[aPerson release];
}
return arrayToReturn;
The [self generateDictionaryOfPeople] method returns an array of NSDictionary objects. Each NSDictionary object has two keys "FIRST_NAME" and "LAST_NAME" with a person's first name and last name as the respective data. The code is looping through each dictionary object in the arrayOfDictionaries array and assigning the dictionary data to the relevant property of an aPerson (PersonClass) object. This object is then added to an array which is returned from this method.
When running instruments I am getting a leak for the dictionary objects contained in the arrayOfDictionaries array. The code within the [self generateDictionaryOfPeople] method is calling [dictionaryObject release] on each NSDictionary object as it is created and added to the array, which makes the retain count on the object 1 (as adding the object to the array would make the retain count 2, but then my release message decrements it back to 1).
I assume this leak is because I am never releasing the arrayOfDictionaries array, and thus the NSDictionary objects within the array are never released. If I attempt to release the array at the end of the above segment of code I get a "message sent to deallocated instance" error. I understand why this is occurring, because I am assigning the aPerson object data within a dictionary item (that I am subsequently releasing) but I don't know where else I can release the arrayOfDictionaries array. Any help would be greatly appreciated.
Thanks!
EDIT: Below is the implementation for [self generateDictionaryOfPeople]
- (NSArray *)generateDictionaryOfPeople {
NSMutableArray *arrayFromDatabase = [[[NSMutableArray alloc] init] autorelease];
// ** Query the database for data **
while ( there are rows being returned from the database ) {
// Declare an NSMutableDictionary object
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
// Loop through each column for that row
for ( while there are columns for this row ) {
columnTitle = title_of_column_from_database
columnData = data_in_that_column_from_database
// Add to the dictionary object
[dictionary setObject:columnData forKey:columnTitle];
// Release objects
[columnName release];
[columnTitle release];
}
// Add the NSMutableDictionary object to the array
[arrayFromDatabase addObject:dictionary];
// Release objects
[dictionary release];
}
// Return the array
return arrayFromDatabase;
}
Here,
if ([key isEqualToString:[[NSString alloc] initWithString: #"FIRST_NAME"]])
aPerson.firstName = [dictionary objectForKey:key];
else if ([key isEqualToString:[[NSString alloc] initWithString: #"LAST_NAME"]])
aPerson.lastName = [dictionary objectForKey:key];
Replace them with
if ([key isEqualToString:#"FIRST_NAME"])
aPerson.firstName = [dictionary objectForKey:key];
else if ([key isEqualToString:#"LAST_NAME"])
aPerson.lastName = [dictionary objectForKey:key];
The problem of the leak is you're creating 1 ~ 2 NSString-s per loop without -release-ing them. If you need constant NSString-s, just directly use them.
I am still getting the original leak due to not releasing the arrayOfDictionaries array.
That means you forgot to autorelease it in generateDictionaryOfPeople.
You need to review the memory management rules.
You are not releasing arrayFromDatabase. (The simplest way to avoid this kind of mistake is to use factories and autorelease as early as possible rather than defer releases manually. In this case, use [NSMutableDictionary dictionary] instead of [[NSMutableDictionary alloc] init].)