Вот очень простой ответ на этот вопрос, надеюсь, это упростит проблему, если таковая имеется;
Прежде всего вам необходимо скачать файлы NSData+AES для здесь . Вам просто нужны файлы NSData+AES.h и NSData+AES.m вместе с файлами cipher.h и cipher.m. Оказавшись под стражей, добавьте файлы в свой проект Xcode и удалите заголовок #import Cocoa/Cocoa.h> из NSData+AES.h и cipher.h (только для тех, кто собирается программировать для iOS, если для MacOS, пожалуйста, оставьте заголовок быть). Импортируйте NSData+AES.h в свой файл, где вы извлекаете и записываете свой файл plist.
Теперь, когда заложены начальные основы, мы приступаем к использованию этих важных файлов. Что вам нужно понять, так это то, как вы хотите расшифровывать и шифровать свои данные. При первом запуске вам нужно скопировать ваш plist в папку с документами, а затем зашифровать его. Обратите внимание: если вы скопируете его и попытаетесь расшифровать напрямую, он выдаст исключение, поэтому для этого мы будем использовать логическое значение UserDefaults и пропустим расшифровку при первом запуске. Также вам необходимо определить константную строку директивы препроцессора, чтобы использовать секретный ключ для шифрования и дешифрования. Вот что у вас будет в вашем классе DataHandler;
#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];
}
Но при первом заполнении dataDictionary_ мы должны принудительно сохранить его в AppDelegate.m в didFinishLaunching:
DataHandler *dataHandler = [[DataHandler alloc] init];
[dataHandler persistData];
Данные всегда будут зашифрованы в любое время, но в методе copyPlist вы будете заполнять свои модели относительно dataDictionary_ и взаимодействовать с этими моделями. Когда вы закончите, вы сохраните свои модели и снова зашифруете, поэтому ошибок не возникнет. Это простое и довольно работоспособное решение без каких-либо хлопот. Ваше здоровье.
person
Mohsin Khubaib Ahmed
schedule
30.08.2014