writeToFile is overwriting the previous data - iphone

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.

Related

Saving a NSArray that contains a NSDictionary that contains an NSArray of UIImages (and others)

I've seen various questions here pertaining to saving NSArrays/NSDictionaries, but I'm a bit confused about what to do when some of the subelements are UIImages.
To give a little context, the app is essentially a blog-type app. When the user is composing a new entry, their post can contain the following:
Up to 3 images from their photo album
Text
Location
In essence, I'm trying to implement a "Save Draft" functionality to the app if the user decides to temporarily cancel their blog post. When the user cancels the blog post, they will be asked in a UIActionSheet if they would like to save their draft. When the user wants to post again, they can begin from where they left off with their saved draft.
At this point, I would need to save these following objects:
1) NSArray of selected photos
---> contains NSDictionaries (up to 3)
--------> UIImage (large sized version)
--------> UIImage (thumbnail sized version)
2) NSDictionary of NSValues (just some view x,y position data)
3) Text -- NSString data of the blog text they have written
4) Location text -- NString data of their current location
Given that I need to save the above 1~4 data in order to make the "Save Draft" functinality, what is the best way to do this? Should I make a special class to hold all of this data? Also, do I first need to make the UIImages into NSData before I can save them to disk?
Thank you!!
Yes a class/model like structure make more sense and easier to handle as well.
Something like-
Interface Blogdata
NSArray *selectedPhoto;
NSDictionary *positionValues;
NSString *blogText;
NSString *locationText;
and then you can make one more model for photo data;
Interface Photodata
NSDictionary *photo;
UIImage *largeImage;
UIImage *thumbImage;
All of the properties that you mentioned seem like they would belong in a Blog class. Are they already grouped together? A Blog object could capture the state of the draft with variables (properties) of the object being the four things you mentioned. You can then save the Blog object as NSData and read it when the user wants the draft again.
The advantage of this is that you only have to worry about saving one object, instead of having to think about saving four each time (and retrieving them).
The easiest way would be to save the images to the apps documents folder and save the NSArray of filenames and other data that can be represented as text in a drafts.plist.
filenameStr = [NSString stringWithFormat:#"image1.png"];
fileManager = [NSFileManager defaultManager];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
imagePath = [documentsDirectory stringByAppendingString:#"/"];
imagePath = [imagePath stringByAppendingString:filenameStr];
NSData *imageData = UIImagePNGRepresentation(myImage);
[imageData writeToFile:imagePath atomically:YES];

i have xml file in my application that i want to write data into it

I have this xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Favorites>
<favorite id="1">
<title>My first favorite</title>
<latitude>31.369834</latitude>
<longitude>34.798207</longitude>
</favorite>
</Favorites>
and I want to write more "favorite"s into it.
I have all the data I need as strings in my project.
But I can't figure out how to really do it - although I have tried a lot.
can you please help me do it ?
thanks.
I agree with the responders that you should consider using a .plist file. Creating NSDictionary objects of your "Favorite" objects, and saving the array of them.
But, to your immediate question, you could save a NSString representing your XML like this (but again, saving a string based XML means a lot of parsing and interaction methods created by you):
// Build The Path
//
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString * filePath = [paths objectAtIndex:0];
filePath = [filePath stringByAppendingPathComponent:#"favorites"];
filePath = [filePath stringByAppendingPathExtension:#"xml"];
// You Should Have A "Favorite" Objects That Know How To Desribe Themselves...
//
NSString * badWayToDoThis = #"<ThinkAboutUsingDictionaries>Saving The Data to a plist</seriously>";
[badWayToDoThis writeToFile:filePath
atomically:YES
encoding:NSUTF8StringEncoding
error:NULL];
Hope that at the very least gets you towards where you're headed.
You could use a plist and create functions that:
First - creates an array or dictionary from the plist
Second - adds new values to your array/dictionary
Third - saves the dictionary to the same file, overwriting and updating the old version.
So rather that inserting values you just overwrite with an updated version

How to cache or store parsed xml file?

My app parses an xml file from my server, but I want to store parsed xml file and next start of my app, controller initially should load stored xml file, then controller should parse it again to check that there may be an update I did on xml file, if there is, new elements parsed should also be stored again.
I am referring to those app such as magazines, newspaper apps. When you open those kind of apps, it loads stored data that was downloaded previous session. Yet, after it loads, it starts to update the data, and it stores new update again.
Where do I start? What do you guys suggest?
Thanks in advance...
You can use CoreData or SQLite (use Objective-C wrapper FMDB https://github.com/ccgus/fmdb) to persist your XML. Then update the database everytime you see a unique id. Depends on how your XML data is.
It's actually quite easy to store to the documents directory. For example:
NSData *data; //this is your xml file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docs = [paths objectAtIndex:0];
NSString *filename = [NSString stringWithFormat:#"test.xml"];
NSString *path = [docs stringByAppendingPathComponent:filename];
[data writeToFile:path atomically:YES];
Then to retrieve it later, you can get the path like above, but retrieve the file instead of writing it:
NSData *data = [NSData dataWithContentsOfFile:path];
either CoreData or SQLite can do the trick

How to store recorded file in array?

Here is the code that i save audio file in string. After that i add in array. But still not work here..
Is there any options here to store audio file in array after that storing documentdictionary.
fileArray = [[NSMutableArray alloc] initWithContentsOfURL:recordedTmpFile];
fileArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [fileArray objectAtIndex:0];
NSMutableDictionary *recordDictionary = [NSDictionary dictionaryWithContentsOfFile:documentsDirectory];
NSFileManager *fileManager = [NSFileManager defaultManager];
for(int i= 0; i<fileArray.count;i++)
{
NSString *recorded = [fileArray objectAtIndex:i];
NSString *filePath = [recordDictionary stringByAppendingPathComponent:recorded];
newArray = [fileManager fileExistsAtPath:filePath];
}
If any code missing by me than suggest me some specific idea about.
Plz give some response..
I don't want to sound like a dick, but just throwing code at an editor isn't going to work. I don't often write answers like this, but sometimes it needs to be done;
Here's a line-by-line breakdown of what you have written and maybe that will give you an idea of what this snippet is doing:
You create an NSMutableArray called fileArray initialised with the contents of a file. I don't know whether this file is in the correct format or not. documentation
You then overwrite this array with an array of search paths. Incidentally, you've now leaked the memory of the initial array.
You get a string to the Documents directory.
You try to create an NSDictionary from a string rather than in the specific format required by the message. As this is an invalid file recordDictionary is nil documentation
You create a reference to the FileManager
You start a for loop to iterate the contents of fileArray
You get each item in fileArray but this is only a list of directories, not files (see point 2)
You try and create a filePath by appending what you think of as a file to a directory except you are appending a directory (see point 7) to nil (see point 4)
You declare an undimensioned variable and try to assign a BOOL to it documentation
So you've written a lot of code that doesn't do anything. It doesn't work because I doubt you have tried to compile it.
Looking at your question history it seems you ask the same question over and over again. You would be better off starting with a basic introduction to Cocoa and working through that until you understand why your code snippet is so wrong.
All you need to do is to get the location of the file you want to save, and move it to the correct place. Somebody else may just write your code for you, but I won't - I'm not that desperate for the points and I'll just be doing you a disservice. Go back to basics, ask specific questions with some idea of what you've tried and you'll get a far better response

How to save multiple files in bundle in iphone app?

Hi all i am trying to save image in the bundle which i have currently on my view,but the problem is that i can only save one image,if i want to save the another image it replaces the old.I am not getting how to save the multiple images in the bundle then.
Here is my code.
- (void)writeImageToDocuments:(UIImage*)image
{
NSData *png = UIImagePNGRepresentation(image);
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSError *error = nil;
[png writeToFile:[documentsDirectory stringByAppendingPathComponent:#"image.png"] options:NSAtomicWrite error:&error];
}
Please Help me out, how to save multiple images, files e.t.c in bundle
Thanks in advance
You're not saving into a bundle, you're saving into your app's documents directory. There's no bundle aspect to it.
You're using the filename #"image.png" for every file that you save. Hence each new write overwrites the old one. In fact, you write each file twice. To save multiple files, use different file names.
It's also bad form to pass a numeric constant as the 'options:' parameter of NSData writeToFile:options:error: (or indeed, any similar case). The value '3' includes an undefined flag, so you should expect undefined behaviour and Apple can legitimately decline to approve your application. Probably you want to keep the NSAtomicWrite line and kill the one after it.
If you're just looking to find the first unused image.png filename, the simplest solution would be something like:
int imageNumber = 0;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *pathToFile;
do
{
// increment the image we're considering
imageNumber++;
// get the new path to the file
pathToFile = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:
#"image%d.png", imageNumber]];
}
while([fileManager fileExistsAtPath:pathToFile]);
/* so, we loop for as long as we keep coming up with names that already exist */
[png writeToFile:pathToFile options:NSAtomicWrite error:&error];
There's one potential downside to that; all the filenames you try are in the autorelease pool. So they'll remain in memory at least until this particular method exits. If you end up trying thousands of them, that could become a problem — but it's not directly relevant to the answer.
Assuming you always add new files but never remove files then this problem is something you could better solve with a binary search.
File names searched will be image1.png, image2.png, etc.