plist resource file in xcode is not modified when calling writeToFile
Hi y'all
This question is probably more related to a confusion with how to use xcode, but I'm not sure.
So I have a plist file in xcode which I added as a resource. It contains an array of dictionaries. data.plist, for simplicity.
I load the data from this file in my main view controller's viewDidLoad function, no problems there. From there, I can see clearly that the file
(used a call like [[NSBundle mainBundle] pathForResource: @"data" ofType: @"plist"] is loaded from the local directory of the XCode project, i.e. the same folder as the xcodeproj file for my project. However, later on in the app lifecycle, in the app delegate's applicationDidEnterBackground function, I want to save any changes to this plist file. However, when I call pathForResource, it's clear that the file that is being modified is only the plist file inside the builded version of the app in the following path
Users/My Username/Library/Application Support/iPhone Simulator/4.2/Applications/C8F45V22-26C2-5C7G-A105-E038C25F4255/MyApp.app/data.plist
And this file is only accessible through the finder by opening the contents of the .app file. So my question is, how can I get it so that when I modify/over write the contents of that plist file, it will show up in the file that I have in my xcode window under "Resources"? I've looked around extensively to see if other people have had the same issue, but surprisingly I have not been able to find anything (probably not using the right keywords).
This question is probably more related to a confusion with how to use xcode, but I'm not sure.
So I have a plist file in xcode which I added as a resource. It contains an array of dictionaries. data.plist, for simplicity.
I load the data from this file in my main view controller's viewDidLoad function, no problems there. From there, I can see clearly that the file
(used a call like [[NSBundle mainBundle] pathForResource: @"data" ofType: @"plist"] is loaded from the local directory of the XCode project, i.e. the same folder as the xcodeproj file for my project. However, later on in the app lifecycle, in the app delegate's applicationDidEnterBackground function, I want to save any changes to this plist file. However, when I call pathForResource, it's clear that the file that is being modified is only the plist file inside the builded version of the app in the following path
Users/My Username/Library/Application Support/iPhone Simulator/4.2/Applications/C8F45V22-26C2-5C7G-A105-E038C25F4255/MyApp.app/data.plist
And this file is only accessible through the finder by opening the contents of the .app file. So my question is, how can I get it so that when I modify/over write the contents of that plist file, it will show up in the file that I have in my xcode window under "Resources"? I've looked around extensively to see if other people have had the same issue, but surprisingly I have not been able to find anything (probably not using the right keywords).
Thanks for your help.
Anyhow
The short answer is, you don't, and you shouldn't.
It would not make sense to have a running app change the XCode resources directory that is used to build that app. If you did that, you wouldn't be able to build the original app again.
Furthermore, an app's resources are ALSO read-only. On an iOS device, writing a file into the application's bundle will fail. On the simulator it works, but is a very bad idea. Your app should treat it's bundle as read-only even on the simulator.
If you're trying to write some one-time code that builds things like plists that you then want to put into your app, have your app write the files into the documents directory, then open the simulator's documents directory in the finder and manually copy the files into the project's resources directory.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Ok, so then how do I save data changes made in my app? ie. you edit certain things that were loaded from the original plist (eg edit/delete an item in a list) and want to replace them when the application closes. This is something that would occur frequently in almost any application. What is usually done? You said your suggestion was only if I wanted to do a one-time job... but I don't see any other option than loading from resources and loading from "documents"
What I don't understand is the method you describe is essentially the only other way to do it.
I see that you cannot modify the app bundle, so what you have to do is build the file as part of the app bundle and then copy it to the App's Document's directory at run-time. However, your response makes it sound like this is only for one time-use / testing purposes.
Last edited by shimmy; 01-11-2011 at 05:02 PM.
Reason: added detail
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Sorry, I meant in XCode / external to the application for debugging purposes
Anyways, to round off this discussion I have posted some of the code for loading / checking / copying the file, and this is basically copied straight from the apple documentation on plist programming anyhow.
I put the code in the app delegate, applicationDidFinishLaunching. Other code for reading/writing the data is elsewhere.
/*because data stored in app bundle cannot be modified, if there is no data file in the documents directory, copy the one
* saved in the app bundle*/
if ( ![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
NSString* resourceaPath = [[NSBundle mainBundle] pathForResource:@"patientsDictionaries" ofType:@"plist"];
[[NSFileManager defaultManager] copyItemAtPath:resourceaPath toPath:dataPath error:NULL];
}
thanks for your assistance.
Last edited by shimmy; 01-11-2011 at 06:46 PM.
Reason: more details
Hi All,
I'm new to iPhone Development. Im getting a plist from a url. Is there any way to store or update the plist file within my application bundle using xcode or some other way
Quote:
Originally Posted by shimmy
Sorry, I meant in XCode / external to the
application for debugging purposes
Anyways, to round off this discussion I have posted some of the code for loading / checking / copying the file, and this is basically copied straight from the apple documentation on plist programming anyhow.
I put the code in the app delegate, applicationDidFinishLaunching. Other code for reading/writing the data is elsewhere.
/*because data stored in app bundle cannot be modified, if there is no data file in the documents directory, copy the one
* saved in the app bundle*/
if ( ![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
NSString* resourceaPath = [[NSBundle mainBundle] pathForResource:@"patientsDictionaries" ofType:@"plist"];
[[NSFileManager defaultManager] copyItemAtPath:resourceaPath toPath:dataPath error:NULL];
}
Hi All,
I'm new to iPhone Development. Im getting a plist from a url. Is there any way to store or update the plist file within my application bundle using xcode or some other way... Any help please
Quote:
Originally Posted by Duncan C
To quote my previous post:
"Always open, read and write the plist from the documents directory."
You can't modify the applications bundle when the app installed on the phone.
Just use the code above to save the plit file to the document directory, you can do this even if you download the file of the net.
__________________
If my answer helped you, you might want to help me.
Make a donation via PayPal.
Sorry, I meant in XCode / external to the application for debugging purposes
Anyways, to round off this discussion I have posted some of the code for loading / checking / copying the file, and this is basically copied straight from the apple documentation on plist programming anyhow.
I put the code in the app delegate, applicationDidFinishLaunching. Other code for reading/writing the data is elsewhere.
/*because data stored in app bundle cannot be modified, if there is no data file in the documents directory, copy the one
* saved in the app bundle*/
if ( ![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
NSString* resourceaPath = [[NSBundle mainBundle] pathForResource:@"patientsDictionaries" ofType:@"plist"];
[[NSFileManager defaultManager] copyItemAtPath:resourceaPath toPath:dataPath error:NULL];
}
thanks for your assistance.
HI, I copied the above code into "ViewDidLoad" function of a view-based project, it didn't work . The error said that the resourceaPath is nil.
However, when I copied the above code into "ViewDidLoad" function of a Navigation-based project , it works .
The difference between these 2 types of project is the UIViewController and UITableViewController classes. Any one know how to fix this problem in view-based project (i.e. in UIViewController)?
soo?? I'm still confused. the plist can not being modified. But can i do that using core data?. My information will display information i as a developer send so i dont need the user add/delete any row. it will be just me very frequently..
what should i use.. it is driving me crazy. I appreciate your help.
Thank you!
soo?? I'm still confused. the plist can not being modified. But can i do that using core data?. My information will display information i as a developer send so i dont need the user add/delete any row. it will be just me very frequently..
what should i use.. it is driving me crazy. I appreciate your help.
Thank you!
Test run the app.
Open the IOS Simulator menu.
Reset Content and Settings...
If you are using code to read/write .plist it won't bother updating it if it already sees on in that app's bundle. You would have to do this every time you update your plist in xcode.
Hi guys, I'm new to Iphone development.
I'm having problems with saving data like level scores in plist.
As I saw from the discussion that the copying/checking of the plist file code is written in the applicationDidFinishLaunching method.
My question is, where exactly do I write the code for reading and writing data???
I'm confused because reading and writing data includes code like :
It includes allocation. So if I want to write the score in plist after every level and read after every level. Then there will be too many allocations. So where exactly do I put this code. Also how do I read the contents of the whole plist file at once in a NSMutableDictionary???
Plz help!!!
Hi guys, I'm new to Iphone development.
I'm having problems with saving data like level scores in plist.
As I saw from the discussion that the copying/checking of the plist file code is written in the applicationDidFinishLaunching method.
My question is, where exactly do I write the code for reading and writing data???
I'm confused because reading and writing data includes code like :
It includes allocation. So if I want to write the score in plist after every level and read after every level. Then there will be too many allocations. So where exactly do I put this code. Also how do I read the contents of the whole plist file at once in a NSMutableDictionary???
Plz help!!!
Your question is a bit vague, but I'll try to answer anyway.
Reading data can also be done through [NSMutableDictionary dictionaryWithContentsOfFile:], although that's just a semantic difference, especially if you're using ARC.
You write a dictionary, say dic, to file with:
[dic writeToFile: path];
This overwrites what is stored at the file.
You really don't need to worry about allocating memory as you can just store the scores as a member of the class, and update it from the file each time you want to. You can define methods that store/retrieve the plist and overwrite your member variable with the data.
Check the NSDictionary/NSMutableDictionary documentation references for methods that might be useful for you.
There might be better ways to store/retrieve information depending on the context (such as CoreData) but plist is probably easiest for a beginner.
do i have to write the above code in applicationDidFinishLaunching or somewhere else.
I'm confused where to put all these because i want to retrieve all the data in the plist at the time of level selection coz i have assigned stars to the user according to their score and it is displayed with the levels in the level sel screen. and the scores are written at the time of gameplay in the gamescene
do i have to write the above code in applicationDidFinishLaunching or somewhere else.
I'm confused where to put all these because i want to retrieve all the data in the plist at the time of level selection coz i have assigned stars to the user according to their score and it is displayed with the levels in the level sel screen. and the scores are written at the time of gameplay in the gamescene
As I said, if you have a class that manages the loading and saving of the data, you can just store the data in a member variable for that class. Depending on the context, you don't necessarily need to write to file every single time something changes. You could write to file when the view changes, or when the view returns etc. You could just save and manipulate the data within the member variable, and then save it to file at appropriate times.
If you have a class like that, you can initialize the class' dictionary in viewdidload or some init method. You could do it in applicaiton did finish launching, but since you probably go from there into a view controller, you might as well load it there.
Also, in the latest versions of XCode you have something called ARC (Automatic Retain Counting) that eliminates the need for calls to release etc.
Also, another very important point (this was a stumbling block for me too when I was starting out). You can't write to resource files (these are files which you create in*XCode that are part of the application bundle). They are read-only. What you want is to use the documents directory. This is how you get a path for a document: (presented in the form of some useful functions. I use these and other functions in a file that I import to other files in my project so that I can quickly retrieve file paths etc.)