This is a very simple answer to this question, I hope that this will simplify the problem, if any;
First you need to download NSData + AES files for here . You just need NSData + AES.h and NSData + AES.m along with the cipher.h and cipher.m files. Once you are in custody, add the files to the Xcode project and remove the header #import Cocoa / Cocoa.h> from NSData + AES.h and cipher.h (only for those who intend to program for iOS, if for MacOS, please let the header be). Import NSData + AES.h into your file, where you extract and write your plist file.
Now that the initial foundations have been laid, we take care of the use of these important files. What you need to understand is how you want to decrypt and encrypt your data. At the first start, you need to copy your plist to the document folder and then encrypt it. Please note: if you copy it and try to decrypt it, it will generate and exclude, therefore, to satisfy this, make good use of the logical value of UserDefaults and skip decryption at the first start. You also need to define the constant string of the preprocessor directive in order to use the secret key for encryption and decryption. Here is what you have in your DataHandler class;
#import <Foundation/Foundation.h> #import "NSData+AES.h" #define MY_SECRET_KEY @"MY_SECRET_KEY" static NSMutableDictionary *dataDictionary_ = nil; static NSMutableDictionary *allSettings_ = nil; @implementation DataHandler - (id)init { if(self = [super init]) { [self copyPlistData]; } return self; } // Encrypt File - (NSData*)encryptFile:(NSMutableDictionary *)plistDict { NSError *err = nil; NSData *data = [NSPropertyListSerialization dataWithPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 options:0 error:&err]; NSData *file = [data encryptWithString:MY_SECRET_KEY]; return file; } // Decrypt File - (NSMutableDictionary *)decryptFile:(NSData *)data { NSError *err = nil; NSData* newData = [data decryptWithString:MY_SECRET_KEY]; NSPropertyListFormat format; NSMutableDictionary *file = [NSPropertyListSerialization propertyListWithData:newData options:NSPropertyListMutableContainersAndLeaves format:&format error:&err]; return file; } - (void) copyPlistData { NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *path = [documentsDirectory stringByAppendingPathComponent: @"myData.plist"]; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL fileExists = [fileManager fileExistsAtPath:path]; //check if the file exists already in users documents folder //if file does not exist copy it from the APPLICATION bundle Plist file if (!fileExists) { NSLog(@"copying database to users documents"); NSString *pathToSettingsInBundle = [[NSBundle mainBundle] pathForResource:@"mydata" ofType:@"plist"]; BOOL copySuccess = [fileManager copyItemAtPath:pathToSettingsInBundle toPath:path error:&error]; if(copySuccess) { noCopyError_ = YES; } } //if file is already there do nothing else { noCopyError_ = YES; NSLog(@"users database already configured"); } BOOL firstRun = [[NSUserDefaults standardUserDefaults] boolForKey:@"IS_FIRST_RUN"]; if(noCopyError_ && firstRun) { dataDictionary_ = [self decryptFile:[NSData dataWithContentsOfFile:path]]; } else { [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"IS_FIRST_RUN"]; [[NSUserDefaults standardUserDefaults] synchronize]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"mydata.plist"]; dataDictionary_ = (NSMutableDictionary*)[[NSDictionary alloc ] initWithContentsOfFile:plistPath]; NSMutableDictionary *data = (NSMutableDictionary*)[dictionaryDATA_ objectForKey:@"Data"]; allSettings_ = [data objectForKey:@"AllSettings"]; } } - (NSMutableDictionary*) properties { NSMutableDictionary * props = [[NSMutableDictionary alloc]init]; [props setObject: allSettings_ forKey:@"AllSettings"]; NSMutableDictionary * data = [NSMutableDictionary dictionaryWithObject:props forKey:@"Data"]; return data; } - (void)persistData { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"mydata.plist"]; NSMutableDictionary *dict = [self properties]; NSData *encryptedDict = [self encryptFile:dict]; [encryptedDict writeToFile:plistPath atomically:YES]; }
But when filling dataDictionary_ for the first time, we must actively use it in AppDelegate.m in the didFinishLaunching file:
DataHandler *dataHandler = [[DataHandler alloc] init]; [dataHandler persistData];
Data will always be encrypted always, but in the copyPlist method you will populate your models with respect to dataDictionary_ and interact with these models. When this is done, you will save your models and encrypt again, so there will be no errors. This is a simple and fairly practical solution without any hassle. Greetings.
Mohsin Khubaib Ahmed
source share