0

I have a custom plist that I am using to populate UItableViewCells with, I am able to read them perfectly, however when I try to write to my custom plist file it never changes.

NSString *errorDesc = nil;
NSString * plistPath = [[NSBundle mainBundle] pathForResource:@"AdvanceSearchPrefrences" ofType:@"plist"];
NSMutableDictionary *advPrefs = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
[advPrefs setObject:cell.textLabel.text forKey:@"Manuf"];
[advPrefs setObject:selRow forKey:@"ManufNum"];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:advPrefs format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
[plistData writeToFile:plistPath atomically:YES];


NSString * plistPath2 = [[NSBundle mainBundle] pathForResource:@"AdvanceSearchPrefrences" ofType:@"plist"];
NSMutableDictionary *advPrefs2 = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath2];

The advPrefs shows the new values and advPrefs2 shows the old values.

halfer
  • 19,824
  • 17
  • 99
  • 186
HurkNburkS
  • 5,492
  • 19
  • 100
  • 183
  • 1
    What makes you think you can modify files in the bundle? – Hot Licks Jul 02 '14 at 02:13
  • 1
    Hint: `writeToFIle` returns a BOOL return code. Maybe you should check it. – Hot Licks Jul 02 '14 at 02:15
  • It returns no. I thought thats what plists were for, where you could read and write to them for values you would like to keep persistant in your app? – HurkNburkS Jul 02 '14 at 02:18
  • 2
    That's not what your bundle is for. Read up on the iOS file system. – Hot Licks Jul 02 '14 at 02:23
  • What is the difference between this and a settings bundle? effectivly I have one view that is used to set a constant value that will be changed one or twice during the lifetime of the app. is this not what plist's were supposed to be used for? its not something that will be constantly read and written to. – HurkNburkS Jul 02 '14 at 02:33
  • @HotLicks it would be nice if you could explaine why you think this shouldnt be done or cant be done, as far as im aware this is exactly what plists were supposed to be fore? but you make it sound like that is not the case, could you please elaborate.. – HurkNburkS Jul 02 '14 at 02:46
  • It's not the type of file, it's where it is. The bundle is read-only. – Hot Licks Jul 02 '14 at 02:58
  • And you need to read up on the iOS file system to understand where you should put your file. – Hot Licks Jul 02 '14 at 03:16
  • Yea I have read something like this before about plists, I am pretty sure when you first read or write a plist file it creates it as a new object that is read/write specific to the device its loaded on... I will look for the information again but talk about cryptic almost unhelpful one line replies man. – HurkNburkS Jul 02 '14 at 03:22
  • possible duplicate of [ios writeToFile changes don't save](http://stackoverflow.com/questions/10671017/ios-writetofile-changes-dont-save) – jscs Jul 02 '14 at 05:01
  • When you first read or write a file from the bundle, *you* must create a new file, in the writable file system. The "bundle" is essentially a zip file. – Hot Licks Jul 02 '14 at 11:24

2 Answers2

2

You can't directly save over your plist, but what you can do is create a copy and save that to NSUserDefaults.

On the initial load you do something like this in your AppDelegate. This will copy your plist into something you can edit and save:

    NSString * plistPath = [[NSBundle mainBundle] pathForResource:@"AdvanceSearchPrefrences" ofType:@"plist"];
    NSMutableDictionary *advPrefs = [NSDictionary dictionaryWithContentsOfFile:plistPath];
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:advPrefs] forKey:@"plist"];
    [[NSUserDefaults standardUserDefaults] synchronize];

In your class that you want to fetch the copied plist, you can call something like this:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [defaults objectForKey:@"plist"];
    NSMutableDictionary *advPrefs = [[NSKeyedUnarchiver unarchiveObjectWithData:data]mutableCopy];

Then make your changes

    [advPrefs setObject:cell.textLabel.text forKey:@"Manuf"];
    [advPrefs setObject:selRow forKey:@"ManufNum"];

And then save them to NSUserDefaults

    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:advPrefs] forKey:@"plist"];
    [[NSUserDefaults standardUserDefaults] synchronize];

I had this same problem with my app and this is how I fixed it. Hope this works for you too

Alex J
  • 1,029
  • 6
  • 8
0

Read data:

NSData *data;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"AdvanceSearchPrefrences.plist"];
if (filePath) {
    data = [[NSString stringWithContentsOfFile:filePath
                                      encoding:NSUTF8StringEncoding
                                         error:&error]
                             dataUsingEncoding:NSUTF8StringEncoding];
    // use data here....
}

Write data:

NSString *documentDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentDirectoryPath stringByAppendingPathComponent:@"AdvanceSearchPrefrences.plist"];
if ([dataToBeWritten writeToFile:path
                      atomically:YES
                        encoding:NSUTF8StringEncoding
                           error:&error]) {
    // data is written
}
ndraniko
  • 814
  • 1
  • 8
  • 14