Save string to plist remove old data - ios

I successfully added my dictionary to plist but when i add 2nd time it remove my old dictionary from my plist.
Here is my code :
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"favQuote.plist"];
NSDictionary *plistDict = [[NSDictionary alloc] initWithObjectsAndKeys:self.txtQuote.text,#"quote",self.lblAuthor.text,#"author",nil];
NSError *error = nil;
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 options:NSPropertyListWriteStreamError error:&error];
if(plistData)
{
[plistData writeToFile:plistPath atomically:YES];
NSLog(#"Data saved sucessfully");
}
else
{
NSLog(#"Data not saved");
}
How do I add my new dictionary without losing old data?

You should store your dictionary of array in your document directory something like,
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"favQuote.plist"];
NSFileManager *manager = [NSFileManager defaultManager];
NSMutableArray *arr = [[NSMutableArray alloc]init];
if ( [manager fileExistsAtPath:plistPath]) {
NSData *data = [NSData dataWithContentsOfFile:plistPath];
arr = (NSMutableArray*)[NSKeyedUnarchiver unarchiveObjectWithData:data];
}
NSDictionary *plistDict = [[NSDictionary alloc] initWithObjectsAndKeys:#"test",#"quote",#"test2",#"author",nil];
[arr addObject:plistDict];
NSData *plistData = [NSKeyedArchiver archivedDataWithRootObject:arr];
if(plistData)
{
[plistData writeToFile:plistPath atomically:YES];
NSLog(#"Data saved sucessfully");
}
else
{
NSLog(#"Data not saved");
}
then you can retrieve and use your values like,
NSMutableArray *arr1 = [[NSMutableArray alloc]init];
if ( [manager fileExistsAtPath:plistPath]) {
NSData *data = [NSData dataWithContentsOfFile:plistPath];
arr1 = (NSMutableArray*)[NSKeyedUnarchiver unarchiveObjectWithData:data];
}
if (arr1.count > 0) {
NSDictionary *firstDic = [arr1 objectAtIndex:0];
}

Related

Unable to save data to plist

Below is my method to save data:
self.doctorString = #"Doctor Bob";
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"doctorprofile.plist"];
NSDictionary *plistDict = [[NSDictionary alloc] initWithObjects: [NSArray arrayWithObjects: self.doctorString, nil] forKeys:[NSArray arrayWithObjects: #"DoctorName", nil]];
NSError *error = nil;
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
if(plistData){
[plistDict writeToFile:plistPath atomically:YES];
NSLog(#"Data saved successfully");
NSLog(#"Error : %#",error);
}else{
NSLog(#"Data not happily saved");
}
My plist structure as below:-
It returns Data saved successfully message but when I checked on the plist file, it is not saved there.
As per my reading of the code given, it will only write the key for DoctorName with the value of Doctor Bob. There is no error in the code itself. You can check the return value of writeToFile method as per below.
BOOL ret = [plistDict writeToFile:plistPath atomically:YES];
if the return value is YES the data is written to .plist file.

NSCFArray objectForKey crash?

I am trying to do something relatively simple. I have a .plist in my bundle and I am trying to save it to the documents directory with encryption. Now before I tried added encryption, it worked fine. However a new crash has arose.
This is how I save my .plist:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"GameSave" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:bundle];
[NSKeyedArchiver archiveRootObject:plistData toFile:path];
plistData = [plistData AES256EncryptWithKey:#"536335"];
[plistData writeToFile:path atomically:YES];
}
Then this is how I retrieve my .plist (and later change a value and re-save)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
//Get array and then current level dict
NSData *plistData = [[NSData alloc] initWithContentsOfFile:path];
plistData = [plistData AES256DecryptWithKey:#"1111"];
NSMutableArray *savegameArray = [[NSKeyedUnarchiver unarchiveObjectWithData:plistData] mutableCopy];
int objectIndex = [Singleton sharedInstance].levelNumber - 1;
NSMutableDictionary *levelDict = [[savegameArray objectAtIndex:objectIndex] mutableCopy];
[levelDict setObject:videoID forKey:#"RecordingURL"];
//Now put new dict back in array
[savegameArray replaceObjectAtIndex:objectIndex withObject:levelDict];
NSData *savedarrayData = [NSKeyedArchiver archivedDataWithRootObject:savegameArray];
savedarrayData = [savedarrayData AES256EncryptWithKey:#"1111"];
[savedarrayData writeToFile:path atomically:YES];
However, in the read code every time I get to this line: NSMutableArray *savegameArray = [[NSKeyedUnarchiver unarchiveObjectWithData:plistData] mutableCopy]; There is a SIGABRT crash which prints:
'-[__NSCFArray objectForKey:]: unrecognized selector sent to instance
0x16604140'
What am I doing wrong?
As we discovered through our chat, we had to first convert the decrypted NSData object to a proper NSPropertyListSerialization serialization.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Hi.plist"];
NSData *plistData = [[NSData alloc] initWithContentsOfFile:path];
NSData *newData = [plistData AES256DecryptWithKey:#"1111"];
NSPropertyListFormat format;
NSMutableArray *savegameArray = [[NSPropertyListSerialization propertyListFromData:newData mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:nil]mutableCopy];
NSLog(#"Array: %#",savegameArray);
You just need to allocate memory to your NSMutableArray like...
NSMutableArray *arrayName = [[NSMutableArray alloc] init];
Until you do that crash will arose..
Hope this is helpful.
Thanks,
Rajesh..

Fetch Images from NSArray of FilePath?

I am trying to fetch Images which i am storing in directory which i have shown in below code . I have tried a lot in StachOverFlow And Chats but not able to achieve the task . Actually i want to generate array of images from the array of filePath which are storing the path of images . Which i will show in UICollectionView . Please check my code and tell me what all can be done to achieve the needed . Thanks in advance
I have array of filepath already generated , i just want to fetch images from them and show it in grid view
-(void)plistRender{
// get paths from root direcory
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:#"PhotoBucket.plist"];
//pngDATA.....
NSString *totalName = [NSString stringWithFormat:#"EGK_%# ", [NSDate date]];
PhotodocumentsPath = [paths objectAtIndex:0];
PhotofilePath = [PhotodocumentsPath stringByAppendingPathComponent:totalName]; //Add the file name
NSData *pngData = UIImagePNGRepresentation(printingImage);
//Write image to the file directory .............
[pngData writeToFile:[self documentsPathForFileName:PhotofilePath] atomically:YES];
[photos_URL addObject:PhotofilePath];
[photos addObject:totalName];
[grid_copy addObject:[NSNumber numberWithInteger:count]];
[grids addObject:whichProduct];
[Totalamount addObject:[NSNumber numberWithInteger:amt]];
NSDictionary *plistDictionary = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: photos,grids,grid_copy,Totalamount,nil] forKeys:[NSArray arrayWithObjects: #"Photo_URL",#"Product",#"Copy",#"Amount", nil]];
NSString *error = nil;
// create NSData from dictionary
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistData)
{
// write plistData to our Data.plist file
[plistData writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
}
NSString *string = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
NSLog(#" plist Data %#", string);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"PhotoBucket"]){
RecipeCollectionViewController *photoBucket = [segue destinationViewController];
NSLog(#"Prepare Segue%#",photoBucket.photoCollection);
NSLog(#"Number of photos %#",photos_URL);
NSMutableArray *imgQueue = [[NSMutableArray alloc] initWithCapacity:photos_URL.count];
for (NSString* path in photos_URL) {
[imgQueue addObject:[UIImage imageWithContentsOfFile:path]];
}
photoBucket.photoCollection = imgQueue;
}
}
try this
for(int i=0;i<[filePathsArray count];i++)
{
NSString *strFilePath = [filePathsArray objectAtIndex:i];
if ([[strFilePath pathExtension] isEqualToString:#"jpg"] || [[strFilePath pathExtension] isEqualToString:#"png"] || [[strFilePath pathExtension] isEqualToString:#"PNG"])
{
NSString *imagePath = [[stringPath stringByAppendingFormat:#"/"] stringByAppendingFormat:strFilePath];
NSData *data = [NSData dataWithContentsOfFile:imagePath];
if(data)
{
UIImage *image = [UIImage imageWithData:data];
}
}
}
Hi you can fetch like this:
NSArray *pathPlist1 =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryStr1 = [pathPlist1 objectAtIndex:0];
NSString *plistLocation1 =
[documentsDirectoryStr1 stringByAppendingPathComponent:#"ImageStorage"];
NSFileManager *filemgr;
NSArray *filelist;
int i;
filemgr =[NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:plistLocation1 error:NULL];
NSLog(#"filelist =%lu",[filelist count]);
cacheImagesArray=[[NSMutableArray alloc] init];
cacheImagesDataArray=[[NSMutableArray alloc] init];
for (i = 0; i < [filelist count]; i++){
NSLog(#"%#", [filelist objectAtIndex: i]);
NSString *imageName=[NSString stringWithFormat:#"%#",[filelist objectAtIndex: i]];
NSString *path=[NSString stringWithFormat:#"%#/%#",plistLocation1, [filelist objectAtIndex: i]];
NSLog(#"Path is =%#",path);
NSData* data = [NSData dataWithContentsOfFile:path];
[cacheImagesDataArray addObject:data];
[cacheImagesArray addObject:imageName];
}
thanks

Check if an array of NSDictionary contains a NSDictionary

In my app I've to check if in an array of NSDictionary there are another NSDictionary. In other words, I made a JSON file and I store it in Documents.
Now I'm parsing this JSON to insert a new entry, before I insert this entry in my JSON I need to check if the entry it's already stored in my file. I parsed JSON so:
// First I read the JSON file from the folder Documents
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"data.json"];
NSString *content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictContent = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Json parsing
NSMutableArray *array = [[NSMutableArray alloc]init];
NSMutableArray *arrayOfDictData = [[NSMutableArray alloc]init];
if (dictContent) {
NSDictionary *sites = [dictContent objectForKey:#"sites"];
NSArray *site = [sites objectForKey:#"site"];
array = [site mutableCopy];
}
Then I've another NSDictionary (dictForJson) in which I inserted the data parsed from the HTML site, so now I need to check if the data in the dictionary dictForJson are still in the JSON file.
How I can check that?
The dictForJson has this structure:
dictForJson = #{#"name": htmlTitle,
#"src": path,
#"expiryDate": expireDate};
the NSArray site has this structure:
site: (
{
expiryDate = "29 Ago 2013";
name = Sito4;
src = "/Users/redoddity/Library/Application Support/iPhone Simulator/6.1/Applications/2D9EBE71-4365-448D-8AD2-A08749B8DBC1/Documents/Sito4.html";
}
)
Have you any idea?
I tried with [array containsObject:dictForJson], but the NSDictionary isn't ordered so when I use this method sometimes returns 0 and other times returns 1
Maybe it's useful I build my JSON with the following code:
- (void)JsonCreateOrEdit {
NSDictionary *dictSites = [[NSDictionary alloc]init];
NSDictionary *dictSite = [[NSDictionary alloc]init];
NSMutableArray *site = [[NSMutableArray alloc]init];
NSDictionary *dictForJson = [[NSDictionary alloc]init];
dictForJson = #{#"name": htmlTitle,
#"src": path,
#"expiryDate": expireDate};
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"data.json"];
BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (!fileExist) {
[site addObject:dictForJson];
dictSite = #{#"site": site};
dictSites = #{#"sites": dictSite};
// Creo il file Json
NSLog(#"Il file non esiste");
SBJsonWriter *writer = [[SBJsonWriter alloc]init];
NSString *jsonCommand = [writer stringWithObject:dictSites];
[CreateFile createFileIn:documentsPath with:#"data.json" andData:jsonCommand]; // This is a class method I made to create the file
else {
// Here there are the instructions to update the file data.json
NSLog(#"Il file esiste");
// Leggo il file json
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"data.json"];
NSString *content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictContent = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Faccio il parsing del json
NSMutableArray *array = [[NSMutableArray alloc]init];
NSMutableArray *arrayOfDictData = [[NSMutableArray alloc]init];
if (dictContent) {
NSDictionary *sites = [dictContent objectForKey:#"sites"];
NSArray *site = [sites objectForKey:#"site"];
array = [site mutableCopy];
// Here I must check if in the array site there are the same information I'm trying to insert
}
}
NSPredicate *aPredicate = [NSPredicate predicateWithFormat:#"%K LIKE[c] %#", #"name", #"htmlTitle"];
NSArray *theFilteredArray = [mainArrayOfDictionry filteredArrayUsingPredicate:aPredicate];
if ([theFilteredArray count]){
NSLog(#"Dictionay Exists");
}else{
NSLog(#"Dictionay does not Exists");
}
In the first statement the first parameter is the "Key" and the second parameter is the actual value of the dictionay.
I am Assuming following :
NSDictionary *dictForJson = #{#"name": htmlTitle,
#"src": path,
#"expiryDate": expireDate};
NSArray *mainArrayOfDictionry = (
"dictForJson" : #{#"name": htmlTitle,
#"src": path,
#"expiryDate": expireDate};
),
(),
(),
(),
.
.
.
)
*Hope this will help you.*Array
I did it! :)
I made so:
{
// Aggiorno il file
NSLog(#"Il file esiste");
// Leggo il file json
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"data.json"];
NSString *content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictContent = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Faccio il parsing del json
NSMutableArray *array = [[NSMutableArray alloc]init];
NSMutableArray *arrayOfDictData = [[NSMutableArray alloc]init];
if (dictContent) {
NSDictionary *sites = [dictContent objectForKey:#"sites"];
NSArray *site = [sites objectForKey:#"site"];
NSDictionary *dict = [site objectAtIndex:0];
NSLog(#"dictForJson = %#\ndict = %#", dictForJson, dict);
NSString *name = [dict objectForKey:#"name"];
NSLog(#"name: %#", name);
array = [site mutableCopy];
}
And it works! Thank you for the time!

Adding Array to PLIST

I am trying to add and array to a Root array in my plist:
And is not working. Here's my code:
-(IBAction)addName:(id)sender{
NSArray *arrayValues = [NSArray arrayWithObjects: nameLabel.text, nameDate.text, nameValue.text, nil];
NSString *plistpath = [[NSBundle mainBundle] pathForResource:#"Names" ofType:#"plist"];
NSMutableArray *namesNew = [[NSMutableArray alloc] initWithContentsOfFile:plistpath];
[namesNew addObject:arrayValues];
[namesNew writeToFile:plistpath atomically:YES];
}
What am I doing wrong? Thanks!
You need to move the file to NSDocumentDirectory. Then edit the plist file.
For example:
Moving to NSDocumentDirectory:
-(NSDictionary *)copyBundleToDocuments
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"Names.plist"];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *bundlePlistPath = [bundlePath stringByAppendingPathComponent:#"Names.plist"];
//if file exists in the documents directory, get it
if([fileManager fileExistsAtPath:documentPlistPath])
{
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return documentDict;
}
//if file does not exist, create it from existing plist
else
{
NSError *error;
BOOL success = [fileManager copyItemAtPath:bundlePlistPath toPath:documentPlistPath error:&error];
if (success) {
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return documentDict;
}
return nil;
}
}
Then get the plist:
-(void)plistArray:(NSArray*)array
{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//getting the plist file name:
NSString *plistName = [NSString stringWithFormat:#"%#/Names.plist",
documentsDirectory];
NSMutableArray *namesNew = [[NSMutableArray alloc] initWithContentsOfFile:plistName];
[namesNew addObject:arrayValues];
[namesNew writeToFile:plistName atomically:YES];
return nil;
}
The plist should be a dictionary as the base object instead of an array.
NSMutableDictionary *namesNew = [NSMutableDictionary dictionaryWithContentsOfFile:plistpath];
[namesNew setObject: arrayValues forKey: #"Root"];
[namesNew writeToFile:plistpath atomically:YES];
You cant write your plist to the bundle you need to use NSDocumentDirectory or NSCachesDirectory
Just copy your plist to bundle the overwrite it.
Note: learn the difference between NSCachesDirectory and NSDocumentDirectory
https://developer.apple.com/icloud/documentation/data-storage/
Copy your plist from bundle to documents(in below code caches), you need to this only one time if your plist in your bundle, I prefer using this code in appdelegate.m when - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Names.plist"];
NSString *plistInDocuments=#"Names.plist";
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:plistInDocuments];
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]){
[[NSFileManager defaultManager] copyItemAtPath:sourcePath
toPath:dataPath
error:&error];
}
NSLog(#"Error description-%# \n", [error localizedDescription]);
NSLog(#"Error reason-%#", [error localizedFailureReason]);
Get your file and overwrite it
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistInDocuments=#"Names.plist";
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:plistInDocuments];
//add object here
NSMutableArray *namesNew = [[NSMutableArray alloc] initWithContentsOfFile:dataPath];
[namesNew addObject:arrayValues];
NSError *error = nil;
if ([myFile writeToFile:dataPath options:NSDataWritingAtomic error:&error]) {
// file saved
} else {
// error writing file
NSLog(#"Unable to write plist to %#. Error: %#", dataPath, error);
}

Resources