How can i save, retrieve, delete & update my data in Plist file in ios?
I am going through with screenshot and step by step. Please follow this and you will get your answer.
First you have to create Property List through your Xcode.
Step:1
Step:2
Step:3
Save data on your save button action :
// Take 3 array for save the data .....
-(IBAction)save_Action:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"manuallyData.plist"];
[self.nameArr addObject:self.nameField.text];
[self.countryArr addObject:self.countryField.text];
[self.imageArr addObject:@"image.png"];
NSDictionary *plistDict = [[NSDictionary alloc] initWithObjects: [NSArray arrayWithObjects: self.nameArr, self.countryArr, self.imageArr, nil] forKeys:[NSArray arrayWithObjects: @"Name", @"Country",@"Image", nil]];
NSError *error = nil;
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if(plistData)
{
[plistData writeToFile:plistPath atomically:YES];
alertLbl.text = @"Data saved sucessfully";
}
else
{
alertLbl.text = @"Data not saved";
}
}
// Data is saved in your plist and plist is saved in DocumentDirectory
Step:4
Retrieve Data from plist File:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"manuallyData.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
plistPath = [[NSBundle mainBundle] pathForResource:@"manuallyData" ofType:@"plist"];
}
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.nameArr = [dict objectForKey:@"Name"];
self.countryArr = [dict objectForKey:@"Country"];
Step:5
Remove data from plist file:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"manuallyData.plist"];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:(NSString *)plistPath];
self.nameArr = [dictionary objectForKey:@"Name"];
self.countryArr = [dictionary objectForKey:@"Country"];
[self.nameArr removeObjectAtIndex:indexPath.row];
[self.countryArr removeObjectAtIndex:indexPath.row];
[dictionary writeToFile:plistPath atomically:YES];
Step:6
Update your data on Update click Action:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"manuallyData.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
plistPath = [[NSBundle mainBundle] pathForResource:@"manuallyData" ofType:@"plist"];
}
self.plistDic = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
[[self.plistDic objectForKey:@"Name"] removeObjectAtIndex:self.indexPath];
[[self.plistDic objectForKey:@"Country"] removeObjectAtIndex:self.indexPath];
[[self.plistDic objectForKey:@"Image"] removeObjectAtIndex:self.indexPath];
[[self.plistDic objectForKey:@"Name"] insertObject:nameField.text atIndex:self.indexPath];
[[self.plistDic objectForKey:@"Country"] insertObject:countryField.text atIndex:self.indexPath];
[[self.plistDic objectForKey:@"Image"] insertObject:@"dhoni.jpg" atIndex:self.indexPath];
[self.plistDic writeToFile:plistPath atomically:YES];
How can i update plist file which has many group item in Objective-C?
First of all, When you retrieve the .plist
file, store it as NSMutableDictionary
.
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"your plist name" ofType:@"plist"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
NSMutableArray *filmsPlaying = [[NSMutableArray alloc] iniWithArray:[dict objectForKey:@"FilmsPlaying"]];
NSMutableDictionary *filmToEdit = [filmsPlaying objectAtIndex:1];// IRL run a loop to get your desired film
NSString *newSeats = @"1-2-9";
[filmToEdit setObject:newSeats forKey:@"ZFILMSEAT"];
[filmsPlaying replaceObjectAtIndex:1 withObject:filmsToEdit];
[dict setObject:filmsPlaying forKey:@"FilmsPlaying"];
Here you have the film you want to edit. After you have made your edition to that dictionary, you need to write it back to App's document dir. (NOTE: You CANNOT save it back to your main bundle but you can write it to Documents instead).
NSString *pathForPlist = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
pathForPlist = [savingPath stringByAppendingPathComponent:@"your plist name.plist"];
[dict writeToFile:savingPath automically:YES];
To edit it in the main bundle without any programming, you can simply open it in any text editor or xcode itself and make your edition. Nothing techie about that.
Save Data to .plist File in Swift
Apparently the file is not in a writable location, so I created it in the documents directory.
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent("data.plist")
var fileManager = NSFileManager.defaultManager()
if (!(fileManager.fileExistsAtPath(path)))
{
var bundle : NSString = NSBundle.mainBundle().pathForResource("data", ofType: "plist")
fileManager.copyItemAtPath(bundle, toPath: path, error:nil)
}
data.setObject(object, forKey: "object")
data.writeToFile(path, atomically: true)
Then, it has to be read from the documents directory.
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent("data.plist")
let save = NSDictionary(contentsOfFile: path)
Updating and saving data in plist
The easiest way to create a dictionary from a plist is to use the method dictionaryWithContentsOfFile:,
For example, to load a plist from your resources:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"playerData" ofType:@"plist"];
NSMutableDictionary *plistdict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
Writing a plistdict is equally simple:
[plistdict writeToFile:filePath atomically:YES];
Note that you can't write into your app's resources, so you'll have to create a different path, e.g. in your Documents directory for your plist.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *docfilePath = [basePath stringByAppendingPathComponent:@"playerData.plist"];
[plistdict writeToFile:docfilePath atomically:YES];
Now retrieve data from plist again.
NSMutableDictionary *plistdict = [NSMutableDictionary dictionaryWithContentsOfFile:docfilePath];
Add your content in plistDict and write it again.
Updating plist file via code
Yes. Writing a file is permanent, as long as you obviously don't delete/move the file somewhere else.
That is a valid option
Yes. If you need a blank file, you don't need it from the bundle. A better idea would be to create it when you need it (when there is something to write). Usually file creations are managed like so
- Check if file exists
- If not, create it.
- Use the file.
If you need a template file (with already some stuff written in it), then a copy from the bundle is more appropriate. But even then, a lot of developers will like to do everything from code, it's not that heavy of a task, and it forces you to create/prepare the right objects and methods from the get-go.
Like Rooe N said, the NSUserDefaults IS a property list, so if you're talking about very simple data, say, like a username and a last-time-I-logged-In-date, you could store it there.
Note that NSUserDefaults are loaded all the way, every time you load the app, so you don't wanna use it as a database. But since you're going for .plist, I'll assume you've already ruled DBs out.
How to read and save data from a remote plist file
No, there isn't a native way to read and write to an external .plist
using just Swift without downloading the file, making changes and re-uploading it. Alternatively, you'd need to set up your own API on a server in order to carry out the read / write actions for you.
As @Scott H stated in the comments, theres a better way to do this:
If you want to go this route, download the file locally, change it
locally, and then upload to the server. However, there are many
alternatives available to you for remote configuration like CloudKit,
Parse, or similar.
Learn more about 3rd party options:
- CloudKit
- Parse
How do I clear the data in a plist created in Xcode?
The simplest thing would be to delete the file using NSFileManager, like this:
[[NSFileManager defaultManager] removeItemAtPath:plistPath error:NULL];
Or if you don't want to do that, assuming the plist is a dictionary, just load the one from your application bundle and then overwrite the one in your documents, like this:
NSDictionary *originalPlist = [NSDictionary dictionaryWithContentsOfFile:bundleFile];
[originalPlist writeToFile:documentsFile atomically:YES];
Which will overwrite the saved file with the original file.
iOS -- NSCoding -- storing data in PList vs Documents Directory
See Archives and Serializations Programming Guide: Serializing Property Lists for a discussion of why, when you're capturing a hierarchical object graph, why "coding (as implemented by NSCoder
and its subclasses) is the preferred way to make object graphs persistent":
Serialization converts Objective-C types to and from an architecture-independent byte stream. In contrast to archiving, basic serialization does not record the data type of the values nor the relationships between them; only the values themselves are recorded. It is your responsibility to deserialize the data in the proper order.
Property list serialization does not preserve the full class identity of the objects, only its general kind—a dictionary, an array, and so on. As a result, if a property list is serialized and then deserialized, the objects in the resulting property list might not be of the same class as the objects in the original property list. In particular, when a property list is serialized, the mutability of the container objects (
NSDictionary
andNSArray
objects) is not preserved. When deserializing, though, you can choose to have all container objects created mutable or immutable.Serialization also does not track the presence of objects referenced multiple times. Each reference to an object within the property list is serialized separately, resulting in multiple instances when deserialized.
Because serialization does not preserve class information or mutability, nor handles multiple references, coding (as implemented by
NSCoder
and its subclasses) is the preferred way to make object graphs persistent.
Bottom line, you'd generally prefer to use NSKeyedArchiver
(or in Swift 4, PropertyListEncoder
) because it captures information about the classes that are encoded and can capture richer types.
Having said that, plists are very simple and are often rendered in text formats that make it easy to visually inspect the resulting data and you can see what was captured. And often, if you're dealing with a nice simple list, plists are a nice, slightly simplified solution.
On updating iOS app, force plist in Documents to be overwritten/deleted?
You can append the bundle version (CFBundleVersion) to the plist you want updated and dynamically load a depending on the bundle version stored in the apps info.plist.
So for version 1.3, you'd load your_plist.1.3.plist
NSString *plistString = [NSString stringWithFormat:@"your_plist_%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];
[[NSBundle mainBundle] pathForResource:plistString ofType:@"plist"];
Related Topics
Xcode 6 - Launch Simulator from Command Line
How to Throttle Search (Based on Typing Speed) in iOS Uisearchbar
Remove Text from Back Button Keeping the Icon
Passing Data to View Controllers That Are Embedded in Container Views
App Killed by Sigkill When Changing Privacy Settings
Is Grouptableviewbackgroundcolor Deprecated on iOS 6
How to Get the Udid in iOS 6 and iOS 7
How to Get a View's Current Width and Height When Using Autolayout Constraints
Does @Synchronized Guarantees for Thread Safety or Not
Difference Between Dispatchqueue.Main.Async and Dispatchqueue.Main.Sync
Instead of Push Segue How to Replace View Controller (Or Remove from Navigation Stack)
Autolayout Is Ignored in Custom Uitableviewcell
Creating Custom Info Window in Swift with the Google Maps iOS Sdk
Uitableview Checkmark Only One Row at a Time
How to Add Http Headers in Request Globally for iOS in Swift
Force Landscape Viewcontroller in iOS 7
Missing Private Key in the Distribution Certificate on Keychain