I'm currently saving an NSDictionary to file on the iOS device. However, NSDictionary files are readable XML. I don't want people to be able to get in and read the contents so I need to be able to encrypt the file on writing and decrypt when loading it back again.
I'm currently saving the file like this:
NSFileManager* fileManager = [NSFileManager defaultManager];
if (!fileManager)
{
NSLog(#"Failed to get file manager to save.");
return;
}
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* filePath = [documentsDirectory stringByAppendingPathComponent:#"save.dic"];
[m_dictionary writeToFile:filePath atomically:YES];
And I'm loading the dictionary like this:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* filePath = [documentsDirectory stringByAppendingPathComponent:#"save.dic"];
m_dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
Can anyone tell me a nice way of encrypting\decrypting this?
Cheers,
Rich
Use a NSKeyedArchiver to create an NSData object from your dictionary (NSKeyedArchiver archivedDataWithRootObject:). Then encrypt the NSData with AES and write that to your file.
Reading takes the reverse: first, read the NSData, decrypt it via the method from the mentioned link, then pass the decrypted NSData to NSKeyedUnarchiver (NSKeyedUnarchiver unarchiveObjectWithData:) and you get your dictionary back.
Related
I want to update my local JSON file in the app when there is a new version of the file. I have the algorithm that checks if there is a new version or not.
But now, I need some code to change/update the local JSON for the online JSON.
I suggest you to use a .plist file as it can easily store a NSDictionary or NSArray (which can be translated from a JSON object)
try the code below:
//store plist file in documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"localJSON.plist"];
if([responseObject isKindOfClass:[NSArray class]])
{
//its an array
NSArray * dataToStore = jsonObject;
[dataToStore writeToFile:filePath atomically:YES];
}
else
{
//its a dictionary
NSDictionary * dataToStore = jsonObject;
[dataToStore writeToFile:filePath atomically:YES];
}
I am trying to save some NSData in pdf format. The NSData is from a downloaded pdf. This is how I tried to do it:
NSData* data = [DKStoreManager loadFileWithName:_FileName forFolderNumber:[_FolderNumber intValue] forUser:userID andType:_FolderType];
NSDictionary *myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSData* dataFile;
NSMutableDictionary* dict = [myDictionary objectForKey:#"MultiFileOtherFile2"];
dataFile = [dict objectForKey:#"FileData"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:#"mLocalFileName.pdf"];
[dataFile writeToFile:pdfPath atomically:YES];
NSString *phrase = nil; // Document password (for unlocking most encrypted PDF files)
ReaderDocument *document = [ReaderDocument withDocumentFilePath:pdfPath password:phrase];
This doesn't work. The only thing that works is:
NSArray *pdfs = [[NSBundle mainBundle] pathsForResourcesOfType:#"pdf" inDirectory:nil];
NSString *filePath = [pdfs lastObject]; assert(filePath != nil); // Path to last PDF file
ReaderDocument *document = [ReaderDocument withDocumentFilePath:filePath password:phrase];
...with a pdf added manually to Xcode!! I even tried all of the conversion solutions at:
How to convert a NSData to pdf in iPhone sdk?
...and none work!
Thanks in advance for any help.
Your issue is not in these lines of code. Your issue is that either:
the downloaded file is corrupt (so your information in the NSData is corrupt)
ReaderDocument, the class you use to open the file, has an bug and downloads the file incorrectly
Maybe the PDF file uses some PDF features which are not supported by your ReaderDocument class? PDF is a very broad format.
Imagine that you are reading json data from the server continuously. let's say, you are getting weather data. I want to show only data 2 hours back from now. Whenever user clicks on the play button, it would show weather data on the map.
How I could save json data first then show it on the map. Because that would enhance my application instead of connecting server , getting data and showing it at the same time. please just give me advice. Do I need to save it first as a plist or an array? Where should I keep this data before I simulate?
Storing it in the plist in the documents directory is a good way of saving data for later reference.If you want to save the JSON string you can also opt for NSUSerDefaults..(preferably if the string is not too large)
Saving to plist..
NSURL *url = [NSURL URLWithString:serverPath];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/myplist.plist", documentsDirectory];
[urlData writeToFile:filePath atomically:YES];
}
and retrieving it..
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"%#/myplist.plist",documentsDirectory ] ];
NSData *retrievedData = [NSData dataWithContentsOfFile:filePath];
I want to save a text string from a file when a user presses a button. Could this file be a .plist? Then, later, I want another function to read the text from the file and turn it into a variable. How is this possible?
Snarky
Saving:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingString:#"/myFile.plist"];
//Create the file if it doesnt exists
if (![[NSFileManager defaultManager] fileExistsAtPath:path]){
NSDictionary *emptyDic = [NSDictionary dictionary];
[emptyDic writeToFile:path atomically:YES];
}
//Save the text using setObject for key or something similar, you could even use a NSArray instead
NSDictionary *dic = [[NSDictionary alloc]init];
[dic writeToFile:path atomically:YES];
Loading:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [NSString stringWithFormat:#"%#/myFile.plist", documentsDirectory];
NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
I think you can't use a .txt file directly but I have never tried it.
If you just want to save some user default setting for future reference, check out NSUserDefaults. Easier than dealing with files if you're really just trying to save some setting.
If you really want to read a string from a file, go to your Xcode organizer, go to documentation, click on the search icon, and type in "Reading Strings From" and one of the top links will be how to read and write to files.
I m able to save the plist file in Simulator but I m not able to save the Plist file in the device. Any suggestion.
I m using
NSString* dictPath = [[NSBundle mainBundle] pathForResource:#"Dictionary" ofType:#"plist"];
NSDictionary * dict = [[NSDictionary alloc] initWithContentsOfFile:dictPath];
to read the files
and
[dict writeToFile:dictPath atomically: YES];
to write to file.
You can not write in to main bundle. You only can read from main bundle. If you want to write an file you need to place it in to the documents directory of your app.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",plistName]];
If you need the plist from the main bundle you can copy it first in to the documents directory then modify it. It is advised to have a check to ensure it is copied only once.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",plistName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]){
NSLog(#"File don't exists at path %#", path);
NSString *plistPathBundle = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
[fileManager copyItemAtPath:plistPathBundle toPath: path error:&error];
}else{
NSLog(#"File exists at path:%#", path);
}
Generally you would store these in ~/Documents or in ~/Library depending on the file. The question What is the documents directory (NSDocumentDirectory)? includes the documentation links and sample code you need to understand this.
You need to save the plist in Documents directory
to write
NSString *mainBundlePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dictPath = [mainBundlePath stringByAppendingPathComponent:#"Dictionary"];
NSDictionary * dict = ...; //Construct your dictionary
[dict writeToFile:dictPath atomically: YES];
to read
NSDictionary * dict = [[NSDictionary alloc] initWithContentsOfFile:dictPath];