My information in a plist isn't saved - iphone

I have some settings in a plist, but when I kill my app I lose all the data stored there.
This is the code that I'm using:
.h
#property (retain, nonatomic) NSString *plistFilePath;
-(IBAction)setHomepage:(id)sender;
.m
#syntehzise plistFilePath;
-(IBAction)setHomepage:(id)sender{
plistFilePath = [NSString stringWithString:[[NSBundle mainBundle] pathForResource:#"settings" ofType:#"plist"]];
NSMutableDictionary *data= [[NSMutableDictionary alloc] initWithContentsOfFile:plistFilePath];
[data setObject:#"http://www.google.com" forKey:#"Homepage"];
[data writeToFile:plistFilePath atomically:YES];
[data release];
}
Am I doing something wrong? Should I use a different class or differents methods? Please help me because I don't know why I store well the information but then when I kill the app I lose it.

As already mentioned the bundle is read only.
Try to avoid setting 'settings' in an a copied plist, as plists are just one more thing to managed. Instead, why not use NSUserDefaults and import your defaults from a defaults plist. For example, add a new plist to your project, and add this to your delegate:
// Get the shared defaults object
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Register the defaults each time the app loads
NSString *defaultsFile = [[NSBundle mainBundle] pathForResource:#"Defaults" ofType:#"plist"];
NSDictionary *defaultsDict = [NSDictionary dictionaryWithContentsOfFile:defaultsFile];
[defaults registerDefaults:defaultsDict];
Now you can save data like this:
// Store the data
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"http://mattmelton.co.uk" forKey:#"HomePage"];
[defaults synchronize];
And retrieve it like this:
// Retrieve data
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *homePage = [defaults objectForKey:#"HomePage"];
And you don't have to worry about external files. Naturally your defaults plist can be platform, user or device specific!
Hope this helps!

The application bundle is readonly. If you want to distribute a file and then update it, move it from the bundle to the documents folder the first time your application runs.

Related

How to store images in cache?

in iphone i have requirement of store image in cache .
but how i can store this in cache.
I know the folder path of cache. is this only way i have to WRITE my image in that folder for cache?
I want to know any other way. or is this correct way?
Please help me.
You can store data on local disk using NSArchiver and NSUnarchiver in this way:
// set your image in cache
NSData *imgData = [NSKeyedArchiver archivedDataWithRootObject:myImage];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:imgData forKey:#"img_01"];
[defaults synchronize];
//get your image from cache
NSData *imgData = [[NSUserDefaults standardUserDefaults] objectForKey:#"img_01"];
myImage = [NSKeyedUnarchiver unarchiveObjectWithData:imgData];
Reference apple here: http://goo.gl/XH2o2
hope this helps.
use this link..
http://www.makebetterthings.com/iphone/image-caching-in-iphone-sdk/
edited:
get file path using this code and fatch the particular file :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];

How do I load and save a plist to and from a string?

I know this sounds like an odd question, but I need to keep a copy of my NSUserDefaults in to a database (my aim is provide a database backup / restore feature, using one file, the database).
So I think I've figured out how to load to a file (although I haven't tried this in xcode).
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults registerDefaults:[NSDictionary dictionaryWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"UserDefaults" ofType:#"plist"]]];
I've googled how to save NSUserDefaults to a plist and to a string and back, but haven't found anything.
You can use the asynchronous NSPropertyListSerialization API or just the synchronous convenience methods on NSDictionary.
Checkout the discussion in the NSDictionary Apple Docs on the writeToFile:automatically method for more info on how it works
Also, This article has some good info on Serialization in cocoa generally.
Use the following code should get you on your way.
//Get the user documents directory
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
//Create a path to save the details
NSString *backedUpUserDefaultsPath = [documentsDirectory stringByAppendingPathComponent:#"NSUserDefaultsBackup.plist"];
//Get the standardUserDefaults as an NSDictionary
NSDictionary *userDefaults = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
//The easiest thing to do here is just write it to a file
[userDefaults writeToFile:backedUpUserDefaultsPath atomically:YES];
//Alternatively, you could use the Asynchronous version
NSData *userDefaultsAsData = [NSKeyedArchiver archivedDataWithRootObject:userDefaults];
//create a property list object
id propertyList = [NSPropertyListSerialization propertyListFromData:userDefaultsAsData
mutabilityOption:NSPropertyListImmutable
format:NULL
errorDescription:nil];
//Create and open a stream
NSOutputStream *outputStream = [[NSOutputStream alloc] initToFileAtPath:backedUpUserDefaultsPath append:NO];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
outputStream.delegate = self; //you'll want to close, and potentially dealloc your stream in the delegate callback
[outputStream open];
//write that to the stream!
[NSPropertyListSerialization writePropertyList:propertyList
toStream:outputStream
format:NSPropertyListImmutable
options:NSPropertyListImmutable
error:nil];
When you want to go backwards you can simply do something like:
NSDictionary *dictionaryFromDisk = [NSDictionary dictionaryWithContentsOfFile:backedUpUserDefaultsPath];
Or you could use the stream/NSData approach from NSPropertyListSerialization, which is similar to the way you save it.

Is it possible to read and update settings plist

Just a quick question. I am bit unsure about this.
When I add a Settings.plist to my Objective C iPhone project and read the settings from it. Is it possible to update settings in this file? Or is this file only readable and should I create a copy at another location like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
and check for its existence at launch?
You can't edit the files you included in your app through Xcode, so you could copy it to the user's document folder.
However, as you're interested in a settings plist file, I advise you to save the settings using NSUserDefaults, which automatically saves a .plist file: In the app's delegate on applicationDidFinishLoading write
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:#"firstRunComplete"]) {
[defaults setObject:optionOne forKey:#"optionOne"]; //replace
[defaults setObject:optionTwo forKey:#"optionTwo"]; //replace
[defaults setBool:YES forKey:#"firstRunComplete"];
[defaults synchronize];
}
And when you want to change one of the options
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:optionOne forKey:#"optionOne"]; //replace
[defaults setObject:optionTwo forKey:#"optionTwo"]; //replace
[defaults synchronize];
Alternatively you can use this method for editing plist files:
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
[plistDict writeToFile:filePath atomically: YES];

iPhone: Updated version doesn't update application binary?

I have couple of applications alive in Apple store and we have just released updated version of these applications with incremented version numbers. I found that all resources are getting updated correctly(updated splash screen, background image etc) but newly added features are not getting updated. For example, I have included a feature so that iPhone app takes new contents from my website. It doesn't happen when I update the application from Appstore updates list.
...but the other strange thing is if I delete the application from my iPhone and download it again from Apple store then everything works fine!! I am not able to understand what has been going on. Anyone could please help me to debug this?
From this I got following code and added in my AppDelegate. For me it always print Version (null). I could see version number correctly set in my Application-info.plist file though!
#if DDEBUG // debugging/testing
NSString *versionString = [NSString stringWithFormat:#"v%#",[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"]];
#else
NSString *versionString = [NSString stringWithFormat:#"Version %#",[[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"]];
#endif // DDEBUG
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:versionString forKey:#"version"];
printf("Version: = %s\n", [versionString cStringUsingEncoding:NSMacOSRomanStringEncoding]);
[defaults synchronize]; // force immediate saving of defaults.
Following code works though! I mean it prints the correct version available in application-info.plist file! Got it from here
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"Version: %#", version);
[defaults setObject:version forKey:#"version_preference"];
[defaults synchronize];
I can confirm if this fixes the issue after resubmitting the application.
Thanks.
This worked:
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"Version: %#", version);
[defaults setObject:version forKey:#"version_preference"];
[defaults synchronize];

Get NSUserDefaults plist file from device

When testing my app on the simulator, I like the ability to edit, or even trash the apps plist file (which contains the NSUserDefaults) from the iPhone Simulator folder. This proves useful when testing (e.g. your app stores a dictionary in there, but you change the model/keys that you use for this data, and therefore need to remove the dictionary stored).
Is it possible to access this file on device (for your own app), without jailbreak?
Thanks in advance
The file is in Library/Preferences. The file is a binary plist with name <iOS application target identifier>.plist (look for the Identifier field in your app target settings), or list the directory contents:
NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
You could also load clean defaults with a #ifdef macro based on some env variable:
#ifdef TESTING
// use the code provided by tsakoyan below
#endif
If you care only for the NSUserDefaults values, this should trash/restore to global defaults all its custom data
NSDictionary *userDefDic = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
NSArray *keys = [NSArray arrayWithArray:[userDefDic allKeys]];
for (NSString *key in keys) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
[[NSUserDefaults standardUserDefaults] synchronize];