How to write data in plist?
Asked Answered
D

6

16

I have created save.plist in a resource folder. I have written some data within that directly (without using coding). I am able to read that data but I'm not able to write through code to the same save.plist. By using following code I am trying to write the data but it gets stored within my .app plist. The code is here

NSString *errorDesc = nil;

NSPropertyListFormat format;

NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"save" ofType:@"plist"];

NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];

NSMutableDictionary *temp = (NSMutableDictionary *)[NSPropertyListSerialization
                     propertyListFromData:plistXML
                              mutabilityOption:NSPropertyListMutableContainersAndLeaves
                  format:&format errorDescription:&errorDesc];

if (!temp) {

    NSLog(errorDesc);

    [errorDesc release];        
    }
    //  [temp setValue:@"123" forKey:@"line1"];
    //  [temp writeToFile:plistPath atomically: YES];

    //Reading data from save.plist
    NSLog([temp objectForKey:@"name"]);
    NSLog([temp objectForKey:@"wish"]);
    NSNumber *num=[temp valueForKey:@"roll"];
    int i=[num intValue];
    printf("%d",i);
        //writitng the data in save.plist

    [temp setValue:@"green" forKey:@"color"];
    [temp writeToFile:plistPath atomically: NO];
    NSMutableDictionary *temp1 = (NSMutableDictionary *)[NSPropertyListSerialization
                propertyListFromData:plistXML                                                            
                                mutabilityOption:NSPropertyListMutableContainersAndLeaves
                format:&format errorDescription:&errorDesc];

    NSLog([temp objectForKey:@"color"]);

I want that, the data which I want to write should get written into save.plist only which is stored in references. I am new with this concept. So if anyone knows it please help me. Thanks in advance. :-)

Depreciable answered 25/5, 2009 at 6:13 Comment(1)
you should probably read the Property List Programming Guide over at iOS reference library.Scottie
V
26

I don't know if I understand your question, but if you want to write into a .plist within your .app bundle you are probably doing something wrong. If you want to store preferences, you should consider using NSUserDefaults.
If you really want to modify a bundled .plist - here is some code:

NSString *plistPath = nil;
NSFileManager *manager = [NSFileManager defaultManager];
if (plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents/Info.plist"]) 
{
    if ([manager isWritableFileAtPath:plistPath]) 
    {
        NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
        [infoDict setObject:[NSNumber numberWithBool:hidden] forKey:@"LSUIElement"];
        [infoDict writeToFile:plistPath atomically:NO];
        [manager changeFileAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] atPath: [[NSBundle mainBundle] bundlePath]];
    }
}

Update:
Nate Flink pointed out that some of the NSFileManager methods used above are deprecated. He posted an answer with the replacement methods below: https://mcmap.net/q/587038/-how-to-write-data-in-plist

Vegetarian answered 25/5, 2009 at 6:36 Comment(3)
I don't want to use NSUserDefault and also I don't want to store data into save.plist within our .app bundle. I want to stored it into save.plist which I created in resource folder. Because whatever changes I got by above code is for temporary basis and also it saved in save.plist within app. So I cant able to see the changes directly without coding.Depreciable
Great solution. I added a modified version below that fixes a deprecated method warning on NSFileManager.Dardar
@weichsel hello, can you answer me, what is the last string in your code [manager changeFileAttributes ...], why you add it and is it valuable?Gremlin
D
9

Updated version of the original awesome example by weichsel (thank you!). Xcode threw a couple warnings one of which is a deprecated method on NSFileManager. Updated here with non-deprecated methods from iOS 5.1

    NSString *plistPath = nil;
NSFileManager *manager = [NSFileManager defaultManager];
if ((plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"mySpecial/PathTo.plist"])) 
{
    if ([manager isWritableFileAtPath:plistPath]) 
    {
        NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
        [infoDict setObject:@"foo object" forKey:@"fookey"];
        [infoDict writeToFile:plistPath atomically:NO];
        [manager setAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] ofItemAtPath:[[NSBundle mainBundle] bundlePath] error:nil];
    }
}
Dardar answered 14/9, 2012 at 16:27 Comment(2)
Why are you setting the modification date of the bundle, rather than the plist?Passus
I can speculate, but in all honesty, I am not sure. It was included by weichsel's original example, and my intent was to show how that exact snippet could be adapted to use the non deprecated methods.Dardar
S
4

When you build the app, it will create an executable file "appName.app" and all the files are built in the bundle. Therefore, you can't access to resource folder when the app is running because all the data is in the bundle(not in folder).

However, you can access to a temp folder which contains some information of the app. You can find the temp folder here: Open finder--click on your username(under PLACES)--Library--Application Support--iPhone Simulator--User--Applications--(here you can find all the temp folders of your iPhone apps)

You can access to this temp folder by:


NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

If you name your file save.plist, you can access to it like this:

NSString *filePath = [documentsDirectory stringByAppendingString:@"_save.plist"];

Then you just save your file to this filePath and it will appear in the temp folder named "Documents_save.plist".

*Note that the temp folder's name varies every time you run the app.

Recommend a book for you: 《Beginning iPhone Development--Exploring the iPhone SDK》. In Chapter 11 you can find what you want.

Stickinthemud answered 25/5, 2009 at 8:44 Comment(0)
A
4

To summarize some of the other answers:

You're problem is that you're trying to write the file back into the folder that contains your application. That folder is not writable at runtime. Everything you're doing is fine, you just need to pick a different location to write your file to.

You can use the NSSearchPathForDirectoriesInDomains function to find a more suitable folder for this data. (Such as the @"Documents" folder.)

Allwein answered 25/5, 2009 at 23:14 Comment(0)
H
1

try this:

-(void)add:(NSRunningApplication *) app { 
   if ([self contains:app]) return; 
   [self.apps addObject:app.localizedName]; 
   [self.apps writeToFile:self.dataFile atomically:YES];
}

from "Cocoa Programming".

Hamburg answered 1/4, 2011 at 15:23 Comment(0)
V
0

you have to copy your plist into document directory... because you cannot save anything without saving into document file....when you copied it will allow to write/modify on plist

Valedictorian answered 6/1, 2011 at 11:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.