Saving a string into file in Objective-C (iPhone) - objective-c

I seem to have stumbled over a problem regarding saving an xml file from a string (this is done on the iPhone)
The file itself exists and included in the project (hence within the workspace), and all indications I get from the code snippet which follows passes without any errors on the emulator and fail on the iPhone (error 513), but in either case the file is not saved!
{
Hits = config->Hits;
NSString* filenameStr = [m_FileName stringByAppendingFormat: #".xml" ];
NSString* pData = [self getDataString]; // write xml format - checked out ok
NSError *error;
/* option 2 - does not work as well
NSBundle *mainBundle = [NSBundle mainBundle];
NSURL *xmlURL = [NSURL fileURLWithPath:[mainBundle pathForResource: m_FileName ofType: #"xml"]];
if(![pData writeToURL: xmlURL atomically: true encoding:NSUTF8StringEncoding error:&error])
{
NSLog(#"Houston - we have a problem %s#\n",[error localizedFailureReason]);
return false;
}
*/
if(![pData writeToFile: filenameStr atomically: FALSE encoding:NSUTF8StringEncoding error:&error])
{
NSLog(#"Houston - we have a problem %s#\n",[error localizedFailureReason]);
return false;
}
return true;
}
Any help would be appreciated,
-A

You should not write to files included in the application package. On a real iPhone, you may be prevented from doing this because these files are digitally signed.
Even if you can modify a packaged file, it is not a good place to store data. Re-installing the application from an App Store upgrade or an Xcode build will overwrite the file with the original.
Instead, store your XML into the Documents directory. You can get the path like this:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* leafname = [m_FileName stringByAppendingFormat: #".xml" ];
NSString* filenameStr = [documentsDirectory
stringByAppendingPathComponent:leafname];
If your file needs some initial state that you don't want to generate in your code, have your app check that it is present in the documents directory the first time it is needed and, if it is missing, copy it from the template in the package.
An alternative to storing structured data is to use user defaults. For example:
[[NSUserDefaults standardUserDefaults] setObject:foo forKey:FOO_KEY];

Related

Objective C can't read text file when running on iPhone

I've made an app that is relying on reading and writing a plist-file. This works well when I'm running the app in the iPhone simulator, but doesn't work at all when I'm testing it on my iPhone. I've also made a pre made text file in .txt format with demo data. The app works when I'm running this file.
All the reading and writing is done in a class that looks like this:
-(void)saveArray:(NSMutableArray *)inputArray
{
albumArray = inputArray;
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolder = [path objectAtIndex:0];
NSString *filePath = [documentFolder stringByAppendingFormat:#"albums.plist"];
[albumArray writeToFile:filePath atomically:YES];
}
Update: Changed the string from "stringByAppendingFormat" to "stringByAppendingPathComponent" and it seems to work now. Thanks a lot! You guys made my day made.
Are you sure, that the folders already exist?
Here is a function i'm using to get the path to my file:
- (NSString*) pathToSavedAlbums
{
NSURL *applicationSupportURL = [self applicationDataDirectory];
if (! [[NSFileManager defaultManager] fileExistsAtPath:[applicationSupportURL path]])
{
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:[applicationSupportURL path]
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (error)
{
NSLog(#"error creating app support dir: %#", error);
}
}
NSString *path = [[applicationSupportURL path] stringByAppendingPathComponent:#"albums.plist"];
return path;
}
Check the spelling of the plist name as well as the case, device is case sensitive for docs but simulator isn't. Also try deleting the app from the device and reinstalling it ?
writeToFile:atomically: returns a bool, so check that to see if it fails to even write to the path. Check the file path string and ensure this is where you want it to go.

move/copy a file to iCloud

I am a beginner using Objective-C. I used the following code to move a file to iCloud but it gives an error that The operation could not be completed. The file exists.
//store the file locally in document folder
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [docPaths objectAtIndex:0];
filePath = [filePath stringByAppendingString:#"/"];
filePath = [filePath stringByAppendingString:fileName];
NSString *writeError = nil;
NSData * fileData = [NSPropertyListSerialization dataFromPropertyList:dataDic format:NSPropertyListXMLFormat_v1_0 errorDescription:&writeError];
if ([fileData writeToFile:filePath atomically:YES]) {
NSLog(#"Server file is stored locally");
}else {
NSLog(#"%#", writeError);
}
// store the file in iCloud folder
NSURL *ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSString *tmpubiquitousURL = ubiquitousURL.absoluteString;
tmpubiquitousURL = [tmpubiquitousURL stringByAppendingString:fileName];
NSURL *ubi2 = [[NSURL alloc] initWithString:tmpubiquitousURL];
[[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:filePathURL destinationURL:ubi2 error:&error];
I used the following to remove the file from iCloud but it gives an error that Cannot disable syncing on an un-synced file.
[[NSFileManager defaultManager] setUbiquitous:NO itemAtURL:filePathURL destinationURL:ubi2 error:&error];
I checked the availability of iCloud in my app delegate and it's available. The file is an XML file (.plist) and I have a local copy stored in NSDocumentDirectory.
Overall, I want to sync that file in iCloud so it will be accessible on all devices using my app. I have been struggling with this for 2 days, so if you could help me to resolve the problem I would appreciate it.
Note: I would rather not to use UIDocument, however, if that is the only option please let me know.
I also have the same problem while using the code
[[NSFileManager defaultManager] setUbiquitous:NO itemAtURL:filePathURL destinationURL:ubi2 error:&error];
you have to change the code like below for this to work correctly
[[[NSFileManager alloc]init]setUbiquitous:YES itemAtURL:filePathURL destinationURL:ubi2 error:nil];
this code is for moving a file to icloud, also you should change the name of the file you are moving. It should not be same.

Parsing of m3u files in Objective-C for iPhone from file system or URL

The example below should take a link from m3u playlist and add it to anArray. (So I will get the NSArray(NSMutableArray) with certain links in it)
NSString *fileContents = [NSString stringWithContentsOfFile:#"myfile.m3u" encoding:NSUTF8StringEncoding error:NULL];
NSArray *lines = [fileContents componentsSeparatedByString:#"\n"];
NSLog (#"%#",lines);
All the time I had (null) in NSLog Message.
All the time when I try NSLog or if/else statement to check is there is link in array it gives me the null object in it.
After that I thought the problem was in m3u type and I've tried to change type in txt and read. (For those who don't know, M3U is just the text in UTF-8 encoding and the changing type should give the result)
Then I've tried the .txt files but it doesn't work too. So there is the code of it.
//Check if there is my file
NSString *addPath = [[NSBundle mainBundle] pathForResource:#"somefile" ofType:#"m3u" ];
if ([fileMgr fileExistsAtPath:addPath] ) {
NSLog(#"Yes.We see the file");
}
else {
NSLog(#"Nope there is no file");
}
//Rename
NSString *path1 = addPath;
NSString *theNewFilename = [path1 stringByReplacingOccurrencesOfString:#"m3u" withString:#"txt"];
NSLog(#"Renamed file adress is %#", theNewFilename);
//Check if there is our renamed file(file manager was allocated before)
NSString *addPath1 = [[NSBundle mainBundle] pathForResource:#"somefile" ofType:#"txt" ];
if ([fileMgr fileExistsAtPath:addPath1] ) {
NSLog(#"Yes we had the renamed file");
}
else {
NSLog(#"No we don't");
}
Checking is there is m3u file worked fine. I had Addres to Renamed file too. But when it was checking is there is renamed file, there was no file (null in NSLog).
After all that stuff, and without any hope to reach my destination I've tried to read txt file line by line separated by /n with 5 links in it.
NSString *fileContents1 = [NSString stringWithContentsOfFile:#"myfile.txt" encoding:NSUTF8StringEncoding error:NULL];
NSArray *lines1 = [fileContents1 componentsSeparatedByString:#"\n"];
NSLog (#"%#",fileContents1);
NSLog (#"%#",lines1);
Both Messages were NULL
One more thing all this stuff I tried to make in -(IBAction)fileRead { } linked to button
(Yes I've presed button every time to check my NSLog)Program was checked in iPhone Simulator. Will be glad if someone say what is the trouble. Also if there is easier way to make this with url. (Tried Couple times with NSUrl and had Nothing but null )
Just because you've changed the path doesn't mean that you've renamed/moved/copied an item, path is just a string. Use NSFileManager methods like
– moveItemAtURL:toURL:error: or
– moveItemAtPath:toPath:error:.
Also, NSString doesn't care about extension, so it's completely safe to read your m3u file to NSString, no need to rename it.
NSString *addPath = [[NSBundle mainBundle] pathForResource:#"somefile" ofType:#"m3u" ];
if ([fileMgr fileExistsAtPath:addPath] ) {
NSLog(#"Yes.We see the file");
NSString *fileContents1 = [NSString stringWithContentsOfFile:addPath encoding:NSUTF8StringEncoding error:NULL];
NSArray *lines1 = [fileContents1 componentsSeparatedByString:#"\n"];
NSLog (#"%#",fileContents1);
NSLog (#"%#",lines1);
}
else {
NSLog(#"Nope there is no file");
}

Adding text file to Xcode project and using it in app

I have a .txt file (in plain text format) and I would like to integrate this into a iOS app I am starting to write. The info in the text file must be searchable by the app. Is there a way to do this? If so, what would be best way to do so? Or would I need to add this text file into ViewController.m in code instead?
You will need to add the txt file to your project and then read it into memory. Here is one way to read the entire contents into memory at once:
NSString *path = [[NSBundle mainBundle] pathForResource:#"yourTextFile"
ofType:#"txt"];
NSError *error = nil;
NSString *data = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:&error];
if (error) {
// handle the error condition
} else {
// continue your processing
}

where does the text file I dragged to xcode go on the iphone/simulator?

I have some data in a .txt file that I dragged over to resources in xcode 4.2. I then use some methods that call upon this file, read it, and display it on the screen to the user. It works. My problem is writing to the end of the same file (aka updating the file based on something the user did) directly on the iphone/ the simulator. It does not write for I feel I am not calling upon the right location and perhaps method. This is my code to write to the end of file, if anyone knows why this is not working it would be tremendous help.
Thank you
-(void)updateFile:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//append filename to docs directory
NSString *myPath = [documentsDirectory stringByAppendingPathComponent:#"Mom.txt"];
fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:myPath];
dateCombinedString= [dateCombinedString lowercaseString];
writtenString= [[NSString alloc]initWithFormat:#", %#, %#, %#",dateString,trimmedString,ForDisplay];
[fileHandle seekToEndOfFile];
[fileHandle writeData:[writtenString dataUsingEncoding:NSUTF8StringEncoding]];
[writtenString release]
}
The file you dragged to Xcode is inside your app resources. You can get the path to resource with this line of code:
NSURL* fileUrl = [[NSBundle mainBundle] URLForResource:#"Mom" withExtension:#"txt"];
However, you cannot modify the files in the resource directory therefore you should first copy that file to your document directory, then modify it with the code in the question.
Here is how you can copy file from resources if the file does not exist on the documents folder:
NSFileManager* fm;
fm = [NSFileManager defaultManager];
//only copy it from resources if it does not exits
if(![fm fileExistsAtPath:myPath]){
NSURL* myUrl = [NSURL fileURLWithPath:myPath];;
NSError* error = nil;
[fm copyItemAtURL:fileUrl toURL:myUrl error:&error];
//handle the error appropriately
}