How to store recorded file in array? - iphone

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

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.

write into plist file using NSDictionary object

Sorry I saw similar questions but they don't seem to have some full answers for me. And i try to put it in order so that people will not hate me or my poor english.
I am working with Xcode 4.2 with storyboard and ARC
I can read from my plist file. My task is simply to write back the updated value(s) to my plist file.
My plist is contain in "supporting files" sub folder of the main folder (where story-board is things goes). the file is call Global.plist and GlobalValue2 is a element of the file type string.
So the read file part looks like this
NSString *plistfile = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistfile];
FirstValueTextBox.text = [[dict valueForKey:#"GlobalValue1"] stringValue];
learn it from some handy youtube video works just fine. updates the value to my text box.
The real problem comes in when I write back my plist file. When i try the following
NSString *plistfile = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
NSMutableDictionary *dict = [NSMutableDictionary
dictionaryWithContentsOfFile:plistfile];
[dict setValue:#"ABC" forKey:#"GlobalValue2"];
SecondValueTextBox.text = [dict valueForKey:#"GlobalValue2"];
[dict writeToFile:plistfile atomically:YES];
the result is I really saw a updated value pop up on the second text box, but the plist file remain unchanged.
The following are the break down of my questions and my guess for the problem
I try to use NSDictionary(not NSMutableDictionary) and call setValue (crash in runtime)
my guess: NSDictionary object itself is readonly so it crash me when i say add value. But why don't it error me when in coding time? if the object is readonly
I use NSMutableDictionary can call setValue. it doesn't crash me and when i call the updated value at "SecondValueTextBox.text = [dict valueForKey:#"GlobalValue2"];" it really return me the updated value. but the content inside of the plist file is not changed. Which is the result I have right now.
my guess: after some search here and there I think "supporting files" is read only too. pure guess did see anyone directly talk about it.
I did try to move on a little more and some people talks about a "document folder" in Xcode that is a read and write place. I think people also talk about write a code to access that folder. Can someone show me the code here.
My last question, can I hook up my Xcode to that "document folder" or where can i see it(the real file folder structure is different from inside Xcode I think). So that i can see and edit my plist file for testing, and i can see the real result without using codes and stuff
I will be much appreciated if people can tell me my guess is right or wrong and the answer to my 3 and 4 question.
In order for your changes to be persisted in your plist, you would indeed need ot copy it from the resource bundle to the documents dirtectory on launch of the application, then use the plist in the documents to read and write.
Here is how you can copy the file:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Global.plist"];
if ([fileManager fileExistsAtPath:plistPath] == NO) {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:#"Global" ofType:#"plist"];
[fileManager copyItemAtPath:resourcePath toPath:plistPath error:&error];
}

fileExistsAtPath API always return NO

Following is my code I need check whether file present in document directory ,But following API does not return true at any condition but file is get created in document directory. Please check any thing wrong I am doing. I have searched on this other says this API "fileExistsAtPath" should work but it is not working in my case. Please do help me.
NSString *recordFile=[NSString stringWithFormat:#"MyFile.acc",data.uid];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentDr = [documentPaths objectAtIndex:0]; // WHY 0 ?
NSString *uniquePath = [documentDr stringByAppendingPathComponent:recordFile];
if([[NSFileManager defaultManager] fileExistsAtPath: uniquePath])
{
NSLog(#"File found")
}
else {
NSLog(#"No File to play");
}
Thanks,
Sony
Probably your path is incorrect. What should be the name of the files you are trying to find? If you have #"MyFile1.acc", #"MyFile2.acc" etc (where 1, 2 is the data.uid value) then try to use this:
NSString *recordFile=[NSString stringWithFormat:#"MyFile%i.acc",data.uid];
Try to append a "/" after documentDr when define uniquePath, or
NSString *recordFile = [NSString stringWithFormat:#"MyFile%#", data.uid];
...
if([NSBundle pathForResource:recordFile ofType:#"acc" inDirectory:documentDr])
the first wrong thing i note is the first instruction.
Why do you pass 'data.uid' as an argument to the format string ? Assuming 'data.uid' is some kind of integer, there should be at least '%d' in...
I had a look to Apple Documentation, in particular, that statement which says
The directory returned by this method may not exist.
You could try getting the current directory path using NSFileManager methods, and then testing for file existence (or create a directory at a place you can easily retrieve later).
What about the others paths ? You wrote 'WHY 0 ?', i'm asking the same question as you.Try looping over the array elements, testing each time for file existence.
The code should work. Your file most likely doesn't exist. Did you use capitalisation in your file name right when saving it?
Also right now, I still don't know what the file name is since, as already said, the first line in your initial post doesn't give the format string right.
Before checking try for existance try:
[[NSString stringWithString:#"test"] writeToFile: uniquePath atomically:YES];
That should create a file at the path and you see, that fileExists works.
I tried many things but ended up that I had to delete the app, clean all targets, and then rebuild again. It's weird that somehow my new resources doesn't get copied to the app. It usually happens to files that when I added them I selected "Create folder references for any added folders".

Locally saved data files are persistant in the emulator but not in the real iPad device... I'm lost

I'm a (kind of) newbie XCode programmer (well, I would say not so newbie nowadays...) and "my pet issue" is: "I'm having trouble saving local files onto my real iPad, compared to saving them with the simulator".
Well to be honest, I have no problem whatsoever SAVING local files, but retrieving them. Why? Because on the simulator my local files seem to persist between compilation sessions, but on the real device, every time the application gets launched (not only after being uploaded from Xcode, but normally launched), data inside the "Documents" directory seems to disappear... So the final user would not be able to store needed historical data between sessions.
Is it a perception of mine? Is it normal behaviour?
The code I use to save this "persistent" data is this one:
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDir = [paths objectAtIndex:0];
NSString *finalPath=[NSString stringWithFormat:#"%#/%#", documentsDir, path];
NSLog(#"Course.m: updatePersistentObject (to disk): final file = %#",finalPath);
[NSKeyedArchiver archiveRootObject:newObject toFile:finalPath];
'path' variable being #".HistoricalTestResults";
The code I use to retrieve data (wheather at boot time, or at runtime) is this one:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#" historical data: Documents paths = %#", paths);
NSString * docsDir = [paths objectAtIndex:0];
NSLog(#"Course.m: loadHistoricalResultsData: docsDir vale [%#]", docsDir);
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSLog(#"Course.m: loadHistoricalResultsData: tmpPath vale [%#]", tmpPath);
NSFileManager *localFileManager = [[NSFileManager alloc] init];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
NSString *file;
while (file = [ dirEnum nextObject])
{
NSLog(#"Historical Data Folder: %#", file);
if ( [[file pathExtension] compare:#"dat"] == NSOrderedSame )
{
NSString *filePath = [NSString stringWithFormat:#"%#/%#", tmpPath, file];
NSLog(#"Course.m: loadHistoricalResultsData: filePath vale [%#]", filePath);
mHistoricalTestList=[[NSKeyedUnarchiver unarchiveObjectWithFile:filePath] retain];
}
}
[localFileManager release];
My exact problem is that while on the simulator, AT BOOT TIME, if I put a trace on the "while" code line, I can see how the enumerator gets some value, and I can iterate among the found files.
On the other hand, when using my iPad, the same breakpoint yields a "nil" pointer when obtaining the enumerator.
As I said, at the beginning of a clean program session, this is normal, so then I need to generate some storable results inside my program memory to store them onto disk.
I do it, and then I write them (both inside the simulator and the iPad). Then I can even re-retrieve this data (from disk) and it seems to still exist inside the Documents folder (both onto the iPad and the simulator).
But then, if I close/kill the program, this data seems to be lost onto the real iPad, and to persist in the simulator.
With this behaviour, my only deduction is "Real iPad programs cannot store persistent data onto their Documents directory". Am I right? (Of course not, because I've seen it work on some other programs).
So I have the feeling I'm doing something wrong, and after wasting TONS of time trying to find it, I'm now asking for advice on stackoverflow...
Every piece of help/insight/hint will be more than welcome.
Something I can think of is that your app is not being installed on the same app sandbox everytime. That means that while in the simulator your path is the same and the documents dir contains the same data, your ipad creates a new directory path for the installation, therefore the data you persisted in the last session won't be accessible.
Another thing that I experienced, was that the simulator was case insensitive when loading up resources, in contrast with the device that is actually case sensitive. In that time I had a strings file with extension .Strings and the iphone was looking for .strings. The simulator would work but the phone showed the keys when LocalizedString() macro was called.
So, tl;dr: verify the paths are the same in the different sessions, and your file names match.
I hope it helps. good luck!
PS: Gaudí rlz.
I'm happy! I was able to solve my own mess (!!?).
I've discovered that, when I originally copied my 2 code snippets, specially the "read part", I didn't copy it literally as it appears on my actual code, I just adapted some variable names and extra stuff that wasn't important here. (Typical situation)
I even did some more things than "removing some unrelated code pieces", (and here comes the important part), as I reordered some of them. And one of the parts I reordered was this one (which didn't work):
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
which I changed (when posting here), onto this other part (which works):
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSFileManager *localFileManager = [[NSFileManager alloc] init];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
There's proably some logic behind this, as "why the first part does work on the emulator, but doesn't on the real device". It seems that "createDirectoryAtPath" is somewhat "resetting" some internal stuff, or maybe asking for an enumerator without having created a directory doesn't make sense...
Whatever the case is, I think my experience is worth enough to keep it here posted for someone who might be in my situation in the future!
Greetings again!

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.