Can you append a NSMutableArray to a file? - iphone

I am trying to write some data from an NSMutableArray to a plist, while keep the old plists content.
The function writeToFile:atomically: overwrites the old contents with the new, I want to append the objects in the new array to the plist.
How can this be done? Thank you.
How can you check for duplicates while doing this?

You could load the contents of the file into an array, then use addObjectsFromArray: in your MutableArray to load the contents into that, then use the writeToFile feature.
i.e.
NSArray *oldArray = [NSArray arrayWithContentsOfFile:filePath];
[newMutableArray addObjectsFromArray:oldArray];
.....
[newMutableArray writeToFile:filePath atomically:YES];

Just create use an instance of NSFileHandle and use -seekToEndOfFile, then do your writing from the array.

Related

writeToFile is overwriting the previous data

I'm using writeToFile property of NSDictionary in my code i'm trying to update a dictionary to documents directory like below,
NSDictionary *revisionDict = [NSDictionary dictionaryWithObject:currentItem.rev forKey:destPath];
NSArray *documentDirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentDirPath objectAtIndex:0];
NSString *dictPath = [documentsDir stringByAppendingPathComponent:#"Revision.dictionary"];
[revisionDict writeToFile:dictPath atomically:YES];
here the problem is my dictionary rather than getting updated by new entries on each iteration it is getting overwitten by new entry.
How can i update my dictionary is there any alternate for writeToFile, Any help is appreciated in advance.
A dictionary in memory can be mutable; a dictionary written to disk is a snapshot of a complete set of information.
You won't get a "merge updates" behavior out of any of the framework methods like this. If you have an existing version that you want to add to or otherwise update, you'll need to load/have the original version in memory as a mutable dictionary, then make the changes or additions to it, and then save the whole new thing (with -writeToFile: or something else).
If you're adding a bunch of entries in a loop, add all the entries first, then write the dictionary to disk as a file when it's done.
Yes writeToFile will overwrite the previous content,
So you can just read the previous content of your file into NSMutableDictionary and then add new content to this mutableDictionary ,and then write this mutableDictionary(which holds both old and new content) to your file path.

iOS - plist file, nsuserdefaults or text data file

I am working on a mobile app which needs a lot of data. Simply put, the data will be for multiple languages and consist of all the words possible for that language. The app would start with only the English language and a lot of it's words. Then the user can choose to download more languages and their data.
I am trying to figure out the best way to read/save/update this data. Should I create a plist file with English data to start with and just keep adding more data as user downloads new languages? Or should I save all the data in nsuserdefaults? Or, should I just include a text file with all the data and parse it on the fly?
Suggestions?
ps: i understand that as this is a mobile app, file space and parsing time have to be considered
Please read my answer here: https://stackoverflow.com/a/7215501/832065
As said in that answer, all NSUserDefaults are stored together in one plist.
A plist and NSUserDefaults are basically the same, however NSUserDefaults should ONLY be used for saving preferences and not a big amount of data. So don't use NSUserDefaults!
I would consider saving this in a plist (NSDictionary). Like this you can have all data sorted in that file. Simply set the "words" (NSString I assume) as object, and the language as key.
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
[dict setObject:words forKey:language];
[dict writeToFile:filePath atomically:YES];
same for reading:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSString *words = [dict objectForKey:language];
EDIT:
If each word is assigned to a number (you can just use NSArray) it doesn't differ much:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
NSArray *words = [NSArray arrayWithObjects:allTheWords,nil];
[dict setObject:words forKey:language];
[dict writeToFile:filePath atomically:YES];
same for reading:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSArray *words = [dict objectForKey:language];
NSString *word = [words objectAtIndex:numberAssignedToWord];
I hope this helps! :)
I would recommend using either an SQL database directly or Core Data. If you have a lot of data, you don't want to load that data completely into memory all the time. It is also easier to handle updates, changes or additions of data.
But your question is so general, and doesn't tell anything on what you actually want to do with the data, how large the data is in KByte or MByte, it is hard to give any good answer.
Writing a lot of data into a text file, user defaults, plist or something similar, doesn't seem the right choice. Using Core Data would be the default way to do such things on iOS.
I thing the easiest way would be to handle the data in a NSMutableArray and store it within the application using NSUserDefaults.
You can handle your data within a NSMutableArray, like so:
NSMutableArray *yourDataStuff = [[NSMutableArray alloc] init];
[yourDataStuff addObject:#"Your data 1"];
[yourDataStuff addObject:#"Your data 2"];
[yourDataStuff addObject:#"Your data 3, etc.."];
Then you can store it using NSUserDefaults, like so:
[[NSUserDefaults standardUserDefaults] setObject:yourDataStuff forKey:#"myData"];
And read your data, like so:
yourDataStuff = [[NSUserDefaults standardUserDefaults] objectForKey:#"myData"];
I think you cannot save large data in the NSUserDefault , and you maybe can not do IO with plist , i had done this , when you read or save , you must read in the whole .plist , and you may reveive memory warning , or crash. you can use C (fread,fwrite) write the data in a .txt , and you may read and write with data stream.

How To remove a key value from Plist in ios?

I wanted to delete the key value in the Plist. I found answers like to delete the value assigned to it and another is to load a new plist but i need to delete a key value
(assuming this is programming-related)
You can load it into an NSDictionary, remove the key/value pair, then write it back:
NSString *pathToPlist = #"/Users/H2CO3/my.plist";
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithCOntentsOfFile:pathToPlist];
[plist removeObjectForKey:#"MyKeyIWannaDelete"];
[plist writeToFile:pathToPlist atomically:YES];
As of now this is not possible via coding. If you have these kind of scenario's, go with the database. So that, you can delete, what ever the row you want?
PlistDict is the Dictionary that is loaded in to the plist .By using following code we can remove the key value from the plist.
[plistDict removeObjectForKey:#"Key"];
Dictionary must be a Mutable one(NSMutableDictionary).

How to save data into an XML file

My application contains 8 TextFields. When I click the submit button I want to save all the values from the TextFields into an XML file (and generate a XML file if required). How can I do this?
Another XML writer which will get the job done is XSWI (shameless plug - I wrote that code).
There are many ways you could do this. One quick and dirty way of doing it is to generate a string in your code and insert the values
e.g.
NSString *myXML = [NSString stringWithFormat:#"<myxml><value1>%#</value1><value2>%#</value2></myxml>", textfield1, textfield2];
Then open a file and write myXML to it.
Not very elegant, but it depends on what exactly you want.
Do you need the XML file to be in a specific format? If not the easiest way is to save it as a plist (a type of xml file) by putting your strings into an array and then saving the array as a plist using
NSArray *array = [NSArray arrayWithObjects:label1.text, label2.text, label3.text, etc, nil];
[array writeToFile:fileName atomically:YES];
The nice thing about the plist is that you can easily load the string again by calling:
NSArray *array = [NSArray arrayWithContentsOfFile:filename];
If you need your XML in a different format from what the plist produces, the easiest way is probably just to build the XML yourself using string concatenation, e.g.
NSString *xml = [NSSString stringWithFormat:#"<root><label>%#</label><label>%#</label><label>%#</label>etc</root>", label1.text, label2.text, label3.text, etc];
You can use GDATAXML to read and write XML to file.
Refer this link to see how its done.
http://www.raywenderlich.com/725/how-to-read-and-write-xml-documents-with-gdataxml

NSArray to plist to TableView

Thanks in advance. I create an array with 6 parts, each an NSString in one of my views. Each string is taken from a UITextField. I want to make a save button that saves the Array into a plist. I then want a TableView to display a table sorted by the first object in the array, the first string.
I've created a blank plist with the name I want and named the plist the same thing as the array. Frankly, I'm lost after that. I don't understand if what I'm making is a dictionary in the plist or an array, and how to do it.
Once the table is made, I think I can handle pushing new views from the selected row.
Anything would help. Thanks and stack overflow has been really helpful.
Thanks again.
If you are really set on using files, to this to write an array to your .plist:
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:theArray forKey:yourKey];
[dictionary writeToFile:#"/somepath/blah.plist" atomically:YES];
[dictionary release];
This will set the root of your .plist file to be a NSDictionary.
If you want it to be an NSMutableArray just change the class of the *dictionary.
Answer via: primary source
To store data it's better to use NSUserDefaults and not files because reading and writing it it's much easier.
There is a primer at: Primer link