0

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

Community
  • 1
  • 1
Howard
  • 19,215
  • 35
  • 112
  • 184

4 Answers4

0

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

  • Silently discards data that contains arrays at the root level.
  • 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
unsynchronized
  • 4,828
  • 2
  • 31
  • 43
0

Probably NSPropertyListSerialization is what you are looking for.

As seen in this Post: Plist Array to NSDictionary

Community
  • 1
  • 1
calimarkus
  • 9,955
  • 2
  • 28
  • 48
  • Documentation: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPropertyListSerialization_Class/Reference/Reference.html – calimarkus Mar 07 '12 at 16:43
0

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.

A-Live
  • 8,904
  • 2
  • 39
  • 74
0

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];
dom
  • 11,894
  • 10
  • 51
  • 74