According to this post I can use the encryption/decryption methods to store/retrieve plist file securely.
But the problem is:
Q: After I have decrypted the plist file, how can I parse and store the plist file as NSDictrionary object
According to this post I can use the encryption/decryption methods to store/retrieve plist file securely.
But the problem is:
Q: After I have decrypted the plist file, how can I parse and store the plist file as NSDictrionary object
One of the possible reasons dictionaryWithData doesn't exist is a property list is not necessarily a dictionary at the root level. It could equally be an NSArray.
Here is my take on a solution: a category that utilises NSPropertyListSerialization
Features
Checks which method to use ( propertyListFromData:mutabilityOption:format:errorDescription: is depreciated )
NSMutableDictionary also supported
Note - this takes an unorthodox approach of wrapping a class factory method with an init method. This is for efficiency - most of the time you will be using the factory method, which just wraps NSPropertyListSerialization, which internally invokes alloc/init/autorelease to return an appropriate object.
NSDictionary+DictionaryWithData.h
#import <Foundation/Foundation.h>
@interface NSDictionary (DictionaryWithData)
+ (id)dictionaryWithData:(NSData *)data;
- (id)initWithData:(NSData *)data;
@end
NSDictionary+DictionaryWithData.m
#import "NSDictionary+DictionaryWithData.h"
@implementation NSDictionary (DictionaryWithData)
+(NSPropertyListMutabilityOptions) mutabilityOption {
return NSPropertyListImmutable;
}
+ (id)dictionaryWithData:(NSData *)data
{
static BOOL methodChecked = NO;
static BOOL use_propertyListWithData = NO;
if (!methodChecked) {
SEL sel = @selector(propertyListWithData:options:format:error:);
use_propertyListWithData = [[NSPropertyListSerialization class]
respondsToSelector:sel];
methodChecked = YES;
}
id result;
if (use_propertyListWithData) {
result = [NSPropertyListSerialization propertyListWithData:data
options:[self mutabilityOption]
format:nil
error:nil];
} else {
result = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:[self mutabilityOption]
format:NULL
errorDescription:nil];
}
return [result isKindOfClass:[NSDictionary class]] ? result : nil;
}
- (id)initWithData:(NSData *)data
{
id result = [[self class] dictionaryWithData:data];
self = result ? [self initWithDictionary:result ] : nil;
return self;
}
@end
@implementation NSMutableDictionary (DictionaryWithData)
+(NSPropertyListMutabilityOptions) mutabilityOption {
return NSPropertyListMutableContainersAndLeaves;
}
@end
Probably NSPropertyListSerialization
is what you are looking for.
As seen in this Post: Plist Array to NSDictionary
You could use core foundation approach here with the method CFPropertyListCreateFromXMLData
If the plist represents the NSDictionary content, the following check should be passed:
if ([(id)plist isKindOfClass:[NSDictionary class]])
and the plist object might be safely casted to NSDictionary. If no, something is wrong with the data or decription process.
The easiest way would be creating a category for NSDictionary like this:
NSDictionaryWithData.h:
@interface NSDictionary (NSDictionaryWithData)
+ (id)dictionaryWithData:(NSData *)data;
- (id)initWithData:(NSData *)data;
@end
NSDictionaryWithData.m:
@implementation NSDictionary (NSDictionaryWithData)
+ (id)dictionaryWithData:(NSData *)data
{
return [[[NSDictionary alloc] initWithData:data] autorelease];
}
- (id)initWithData:(NSData *)data
{
self = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:NULL
errorDescription:nil];
return [self retain];
}
@end
Usage:
NSDictionary* myDict = [[NSDictionary alloc] initWithData:decryptedData];