.plist file writing failed! what is wrong with this code? - objective-c

Nothing is written in my plist file after this code. What is wrong with my code?
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"aFile.plist"];
NSMutableDictionary *reqData = [NSMutableDictionary dictionaryWithContentsOfFile:finalPath];
/*
some modifications to "reqData"
*/
[reqData writeToFile:finalPath atomically:YES];
Nothing is written in file. what could be the problem?

You'd better write to Document folder:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [paths objectAtIndex:0];
Update
According to NSDictionary Class Reference:
This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
Is there any objects with a type other than these valid ones in your whole dictionary?

You are trying to write the file back to the app bundle.
That's what's most likely causing the error.
What if you try writing it somewhere else (e.g. in your desktop folder)?

If you're including the plist with your application, you'll want to copy that file into the Documents directly when the app first starts up (if it hasn't already been copied there). Then, any read and write operations you want to do on the plist should be done from the copy in the Documents directory instead of the version in the app bundle.

First Thing to remember:
You can read a plist file from resources but you can't modify it.
if you want to modify,
copy that file to Documents directory
copy contents of plist into array or dictionary depending on its type
make changes you want
Finally.... save it back to documents directory
that do the trick

Related

How to take parameters from plist?

I am quite new at Objective-C programming, I was asked to develop a framework that could be implemented in IOS apps. This framework has three methods (that take a model object as an argument) that perform API comsumption and return a message (that takes from response). The problem is that I was asked to store the module parameters in plist, and I don´t have a good clue what this means. I been reading about plist and I know they can store serialized objects. But I really don´t understand what it means to be storing all parameters on this file.
A plist is essentially a dictionary (or NSDictionary) -- with keys and values -- written to a specific file format that iOS expects.
To write a plist file is easy when you do it from Xcode. In Xcode 10.3 you can go to "File" -> "New" --> "File..." and select "Property List" from the types of files you see:
I created a file (as an example) named "SomeFile.plist" and then added a couple keys & values to it:
Now after you get this file included in your new project, you need to read the keys & values back in. Here is a related question that shows you different ways to read the plist / dictionary, such as:
NSString *path = [[NSBundle mainBundle] pathForResource: #"YourPLIST" ofType: #"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: path];
NSString *name = [dict stringForKey: #"RaphaelName"];

Why does NSMutableDictionary writeToFile return no?

I have the following, where path is the documents folder. myArray is an NSMutableDictionary. I'm running this in the simulator.
BOOL success = [self.myArray writeToFile:path atomically:YES];
The above always returns no. I can see in the target folder that nothing was written.
The path looks like this:
/Users/username/Library/Application Support/iPhone Simulator/7.1/Applications/79D8982F-9995-4831-83B9-E2749F2261CD/Documents/
Any ideas what I'm doing wrong?
I expect one or more objects within the dictionary cannot be written:
Discussion
This method recursively validates that all the contained
objects are property list objects (instances of NSData, NSDate,
NSNumber, NSString, NSArray, or NSDictionary) before writing out the
file, and returns NO if all the objects are not property list objects,
since the resultant file would not be a valid property list.
Where Property List Objects are (see here):
NSArray, NSDictionary, NSString, NSData, NSDate and NSNumber.
The path points to the Documents directory but not to any particular file in that directory. You can't write a file to a directory, you have to give it a file name. The other obvious possibility would be that self.myArray == nil. Plus what Droppy said is absolutely correct.
/Users/username/Library/Application Support/iPhone Simulator/7.1/Applications/79D8982F-9995-4831-83B9-E2749F2261CD/Documents/
The path just represents a navigation to Documents Directory but not pointing to some kind of file.
Add some file name with the below line and add dictionary to the path
NSArray *sandboxArray=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path= [[arr objectAtIndex:0]stringByAppendingPathComponent:#"login.plist"];
write something similar to the path

Incorporate a text file into the build of my app

I want to incorporate a text file into the "Build" of my program for the iPhone. Other then copying and pasting into the code, how can I do this? I have many data files that I would like to include in the build.
You can use the NSString method stringWithContentsOfFile:encoding:error: to read the contents of any file in your project into an NSString.
Include the file in your project (no copy and paste required). Simply right click on the list of files, select Add, select Existing files, and navigate to the file to include.
Then, in the code where you want to load the file, use
NSString *txtFilePath = [[NSBundle mainBundle] pathForResource:#"myTxtFile" ofType:#"txt"];
NSString *txtFileContents = [NSString stringWithContentsOfFile:txtFilePath encoding:NSASCIIStringEncoding error:&error];
However, if you want to have more structure, then you should use a plist to store an NSDictionary.
You can add a .txt file to your application bundle. Please explain more what actually you want to do?
You can use plists to provide prepared data lists in your app. You can read them in with the NSArray function arrayWithContentsOfFile: or the NSDictionary function dictionaryWithContentsOfFile:.

NSDocumentDirectory or NSBundle resourcePath with Sqlite?

i was wondering why we search a path with NSDocumentDirectory at first here :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"Sports.sqlite"];
and later on we compare this path with another path, using this time resourcePath from the NSBundle :
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"Sports.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath
toPath:writableDBPath error:&error];
What is the difference between both?
In this situation you are (normally one time only, unless you need to restore database) copying the database from your read only bundle into your documents directory so that a user can read/write to it. This is useful if you want to pre-seed a database or just have the structure set up.
Your documents directory is read/write and your bundle is not therefore you need to have the sqlite in your documents directory for it to be used properly.
The first part of code is simply getting you the path for where you want the sqlite file to live in your documents directory. Which ends up being held in writableDBPath.
Next you get the path from your bundle (defaultDBPath) and use the two paths to
... copyItemAtPath:defaultDBPath toPath:writableDBPath ...
This gives you a read/write database that you provide in your bundle. Why would you do this instead of running your SQL on the device to create the schema? This allows you to pre-seed the database with some data. It can sometimes be easier to use a graphical tool to set up and edit your sqlite file
What you mean by "comparing" the two paths?
What I see is a file copy from your app resources directory to the user document directory.
So what is happening is that a default version of Sports.sqlite that is to be bundled with the app (and thus is available in the resources directory) is copied to the user directory where the user can modify it.
The first chunk of code simply build the destination path (a string); the second chunk build the source path (a string) and then makes the copy.
Does it make sense?

Update plist file in File Sharing folder - I really need advice

I need to open a plist file located in the File Sharing folder, to add two pieces of user info to each time the app is launched; as in a new Name and Email of the user (both are of type NSString and the plist file is Dictionary).
It then needs to save the file back to the File Sharing folder again, so that the new updated plist file can be removed at a later time via iTunes.
If anyone could help it would be greatly appreciated
Storing a plist in the Documents directory is possible. You will be able to load the plist into an NSMutableDictionary, modify the dictionary and write it back out to the Documents directory.
// get the path to the plist file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"myfile.plist"];
// read the plist into an NSMutableDictionary
NSMutableDictionary *plistDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
// make the additions to the plistDictionary
// write the plist back to the documents directory
[plistDictionary writeToFile:filePath atomically:YES];
I don't know that you will be able to remove the plist via iTunes.
Another great resource that I found was an article by the "Humble Coder's" blog at the following location. Great advice and the example code was spot on for my need to save retrieve and update my plist files. Thank you again to those that helped.
http://humblecoder.blogspot.com/2010/03/revisited-storing-and-retrieving.html