Write to plist file (In Particular row/Item) - ios

I have a .plist file which have this structure,
I want to add or replace the Item 5. I am using this code
NSError *error ;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Introduction.plist"];
NSMutableArray *data = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSString *comment = str;
[data replaceObjectAtIndex:1 withObject:comment];
[data writeToFile:path atomically:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"Introduction" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
If I change replaceObjectAtIndex: to 5 it changes my plist structure, and I don't want that.
How can I insert/replace the text at the row 5 (Item 5) of particular Index?

You structure has an array of arrays.
[data replaceObjectAtIndex:1 withObject:comment];
By this code you are replacing an array at index 1 with a string. Do you specifically need to insert to 5th index or do you just need to add it to existing sub array?
NSMutableArray *subArray = [data[sectionIndex] mutableCopy];
if (!subArray) {
subArray = [NSMutableArray array];
}
if (rowIndex<[subArray count]) {
[subArray replaceObjectAtIndex:rowIndex withObject:comment];
}else{
[subArray addObject:comment];
}
[data replaceObjectAtIndex:sectionIndex withObject:subArray];
[data writeToFile:path atomically:NO];
Access the subArray, make it mutable and add or insert at specific index. If you are trying to insert don't forget to include a check if the index is not greater than count of that array.

Related

How to make a .plist file

I have an api inside are the city's ID, I do not want to request data every time,I want to writeToFile as plist,but the first written is too slow and memory skyrocketing.
Is there any method I can use to make it into a plist as local file,so users do not have to write again
Plist file obtained in this way is no data on the xcode view, but in fact it has already been written, you can find data through code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *plistPath = [paths objectAtIndex:0];
NSMutableArray *marr = [NSMutableArray array];
NSString *filename=[plistPath stringByAppendingPathComponent:#"city.plist"];
NSLog(#"filename == %#",filename);
[marr addObject:#"字符串"];
[marr writeToFile:filename atomically:YES];
If you are about to create Plist without programmatically then follow these steps :
Right Click on Files and Select 'New File...' option.
Choose Resources from OS X tab.
An option for Property List is available.
Select an give an appropriate name.
This gets added to your project.
You can create a property list in Objective-C if all of the objects in the aggregate derive from the NSDictionary, NSArray, NSString, NSDate, NSData, or NSNumber class.
Use following code:
//Get the documents directory path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"plist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) {
path = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:#"plist.plist"] ];
}
NSMutableDictionary *data;
if ([fileManager fileExistsAtPath: path]) {
data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
}
else {
// If the file doesn’t exist, create an empty dictionary
data = [[NSMutableDictionary alloc] init];
}
//To insert the data into the plist
[data setObject:#"iPhone 6 Plus" forKey:#"value"];
[data writeToFile:path atomically:YES];
//To retrieve the data from the plist
NSMutableDictionary *savedValue = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *value = [savedValue objectForKey:#"value"];
NSLog(#"%#",value);
For more details click here
Apple has also put a demo project for creating plist file here.
I wrote a class that caches API responses, so later when u request Countries endpoint, it will check defined endpoints to cache, if it find it in list and it exist in cache, it will return the cached one and will not complete performing the HTTP request, in docs i provided steps how to implement it.
MGCacheManager
Following function take serilizable object(dictionary, array) as input and convert it into plist and write it in document disrectory of application:
+ (BOOL) writeBundelPlist : (NSString *) plistName with : (id) newPlistData {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:plistName];
if (![fileManager fileExistsAtPath:plistPath]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:[plistName stringByDeletingPathExtension] ofType:[plistName pathExtension]];
NSLog(#"plistPath = %#", plistPath);
[fileManager copyItemAtPath:bundle toPath:plistPath error:&error];
}
return [newPlistData writeToFile:plistPath atomically:YES];
}
this method is very useful, thanks for evervone,thanks for rmaddy
do{
let data = try NSPropertyListSerialization.dataWithPropertyList(response.result.value as! NSMutableDictionary, format: NSPropertyListFormat.XMLFormat_v1_0, options: 0)
data.writeToFile(countryListPath, atomically: true)
}catch
{
}

how to add multiple arrays in plist file programmatically in iPhone

I want to create plist file with multiple array and array as Root type.I can add multiple array in dictionary but I want to add all array in one array programmatically.How is it possible to create plist file programmatically and write array data into it.Please guide me and give some sample links.Thanks.
Here is my code to add array in dictionary :
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Demo.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"Demo" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
firstArray = [[NSMutableArray alloc] initWithObjects:#"15-5-123",#"15-5-12",nil];
secondArray = [[NSMutableArray alloc] initWithObjects:#"TestFiling",#"TestFiling",nil];
thirdArray = [[NSMutableArray alloc] initWithObjects:#"15132561",#"15135601", nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:firstArray forKey:#"firstArray"];
[dictionary setObject:secondArray forKey:#"secondArray"];
[dictionary setObject:thirdArray forKey:#"thirdArray"];
[dictionary writeToFile:path atomically:NO];
NSDictionary *dictionary1;
dictionary1 = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(#"dictionary1 %#",dictionary1);
this code is working fine for dictionary but i want to add arrays in array.
The first section of your code is fine, you just need to switch the second part to using an array:
NSMutableArray *array = [[NSMutableDictionary alloc] init];
[array addObject:firstArray];
[array addObject:secondArray];
[array addObject:thirdArray];
[array writeToFile:path atomically:NO];
NSArray *array1 = [NSArray arrayWithContentsOfFile:path];
NSLog(#"array1 %#", array1);

Writing/ Appending data to Plist returns nill

I am writing data to plist with always returns me the nil value.. I have to append data also to the previous values of array. But Values are always null..
Below is the code:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"a.plist"];
// set the variables to the values in the text fields
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObject:#"c" forKey:#"Id"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
[array addObject:plistDict];
[array writeToFile:plistPath atomically:YES];
NSLog(#"array%#",array);
}
else
{
NSArray *array = [NSArray arrayWithObject:plistPath];
[array writeToFile:plistPath atomically:YES];
}
If I understand your question correctly, I tested the code with just one little change i.e, Added array declaration and it's working fine. Please pardon me if this is not the issue.
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"a.plist"];
// set the variables to the values in the text fields
NSMutableArray *array;
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObject:#"c" forKey:#"Id"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
[array addObject:plistDict];
[array writeToFile:plistPath atomically:YES];
NSLog(#"array%#",array);
}
else
{
NSArray *array = [NSArray arrayWithObject:plistPath];
[array writeToFile:plistPath atomically:YES];
}

writeToFile:atomically: not saving new plist data

I am using writeToFile:atomically: to update the value of a key in my plist by 1 every time the app is launched. I put this code in viewDidLoad, which reads the string value of the key, gets the numeric value of that string, increases it by 1, converts it back to a string, and writes that as the new string for that key, but when I read it again it seems to have not updated. I can't figure out what I'm doing wrong. I don't need a special framework for writeToFile:atomically:, do I?
Here is the code:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"DaysLaunched.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"DaysLaunched" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSMutableDictionary *data1 = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *currentNumberOfDays = [NSString stringWithFormat:#"%#",[plistDict objectForKey:#"numberOfDays"]];
NSLog(#"currentNumberOfDays = %#", currentNumberOfDays); //0
int days = [currentNumberOfDays intValue];
days ++;
currentNumberOfDays = [NSString stringWithFormat:#"%d", days];
[data1 setObject:[NSString stringWithFormat:#"numberOfDays"] forKey:currentNumberOfDays];
NSLog(#"currentNumberOfDays = %#", currentNumberOfDays); //1
[data1 writeToFile: path atomically:YES];
currentNumberOfDays = [NSString stringWithFormat:#"%#",[plistDict objectForKey:#"numberOfDays"]];
NSLog(#"currentNumberOfDays = %#", currentNumberOfDays); //0 ??????? writeToFile isn't working?
And here is a screenshot of "DaysLaunched.plist" in my 'Supporting Files' folder, (I've also verified that the plist file name is spelled exactly the same way I spelled it in my code, via Copy-Paste)
The original plist file is also in my 'Copy Bundle Resources' in targets.
Try
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"DaysLaunched.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"DaysLaunched"
ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableDictionary *plistDict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
NSInteger days = [plistDict[#"numberOfDays"] integerValue];
plistDict[#"numberOfDays"] = [#(++days) stringValue];
[plistDict writeToFile: path atomically:YES];
You have made a mistake while setting your data.
You should do:
[data1 setObject:currentNumberOfDays forKey:#"numberOfDays"];
instead of:
[data1 setObject:[NSString stringWithFormat:#"numberOfDays"] forKey:currentNumberOfDays];

getting data from plist to NSMutableArray and writing the NSMutableArray to same plist iPhone

Using this code I am trying to get the data from Templates.plist file but I am getting null value in array.
//from plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Templates" ofType:#"plist"];
NSMutableArray *arry=[[NSMutableArray alloc]initWithContentsOfFile:path];
NSLog(#"arrayArray:::: %#", arry);
This is my plist file:
Also I want to know how can I add more strings to this plist file and delete a string from this plist.
First off you cannot write to anything in you mainBundle. For you to write to you plist you need to copy it to the documents directory. This is done like so:
- (void)createEditableCopyOfIfNeeded
{
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"Template.plist"];
success = [fileManager fileExistsAtPath:writablePath];
if (success)
return;
// The writable file does not exist, so copy from the bundle to the appropriate location.
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Template.plist"];
success = [fileManager copyItemAtPath:defaultPath toPath:writablePath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable file with message '%#'.", [error localizedDescription]);
}
So calling this function will check if the file exists in the documents directory. If it doesn't it copies the file to the documents directory. If the file exists it just returns. Next you just need to access the file to be able to read and write to it. To access you just need the path to the documents directory and to add your file name as a path component.
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [docDir stringByAppendingPathComponent:#"Template.plist"];
To get the data from the plist:
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
To write the file back to the documents directory.
[array writeToFile:filePath atomically: YES];
-(NSMutableArray *)start1
{
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Templates.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath]){
plistArr = [NSMutableArray arrayWithContentsOfFile: plistPath];
}
else {
plistArr = [[NSMutableArray alloc] init];
}
return plistArr;
}
- (void)createNewRecordWithName:(NSMutableDictionary *)dict
{
plistArr=[self start1];
[plistArr addObject: dict];
//[dict release];
[self writeProductsToFile:plistArr];
}
- (void)writeProductsToFile:(NSMutableArray *)array1 {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Template.plist"];
[array1 writeToFile:plistPath atomically:YES];
}
To get a plist into a mutable array, use this class method:
NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:path];
Then, add/delete strings from the array. To save the array back to a plist, use:
[array writeToFile:path atomically:YES];

Resources