2

I'm not sure if this is possible, but I've seen people do crazy things with regex and other tools.

I want to convert this plist to an Objective-C literals:

<dict>
    <key>ar</key>
    <array>
        <string>+54## #### ####</string>
        <string>## #### ####</string>
    </array>
    <key>at</key>
    <array>
        <string>+43 1 ########</string>
        <string>+43 ############</string>

</dict>

converted to:

NSDictionary *dic = @{ 
     @"ar" : @[@"+54## #### ####", @"## #### ####"],
     @"at" : @[@"+43 1 ########",@"+43 ############"]
};

Is it possible to automate such conversion? This guy did something similiar: he parsed a PHP list into an NSDictionary using VIM.

Community
  • 1
  • 1
Snowman
  • 31,411
  • 46
  • 180
  • 303

3 Answers3

8

Plist don't have a separate 'format' for use in code (this question doesn't quite make sense as-is). You either want to 1. generate Objective-C code which initializes the dictionary with these values, or 2. initialize the dictionary using the file, for which you can write

NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:@"UIPhoneFormats.plist"];

Edit: so you want to generate Objective-C code that in turn will reproduce the same dictionary. For this, you need to re-print the contents of the dictionary in a formatted way. You can write a program like this:

#import <stdio.h>
#import <Foundation/Foundation.h>

NSString *recursiveDump(id object)
{
    if ([object isKindOfClass:[NSString class]]) {
        return [NSString stringWithFormat:@"@\"%@\"", object];
    } else if ([object isKindOfClass:[NSNumber class]]) {
        return [NSString stringWithFormat:@"@%@", object];
    } else if ([object isKindOfClass:[NSArray class]]) {
        NSMutableString *str = [NSMutableString stringWithString:@"@["];
        NSInteger size = [object count];
        NSInteger i;
        for (i = 0; i < size; i++) {
            if (i > 0) [str appendString:@", "];
            [str appendString:recursiveDump([object objectAtIndex:i])];
        }
        [str appendString:@"]"];
        return str;
    } else if ([object isKindOfClass:[NSDictionary class]]) {
        NSMutableString *str = [NSMutableString stringWithString:@"@{"];
        NSString *key;
        NSInteger size = [object count];
        NSArray *keys = [object allKeys];
        NSInteger i;
        for (i = 0; i < size; i++) {
            if (i > 0) [str appendString:@", "];
            key = [keys objectAtIndex:i];
            [str appendFormat:@"%@: %@", recursiveDump(key), recursiveDump([object objectForKey:key])];
        }
        [str appendString:@"}"];
        return str;
    } else {
        // feel free to implement handling NSData and NSDate here,
        // it's not that straighforward as it is for basic data types.
    }
}


int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:@"UIPhoneFormats.plist"];
    NSMutableString *code = [NSMutableString stringWithString:@"NSDictionary *dict = "];
    [code appendString:recursiveDump(dict)];
    [code appendString:@";"];
    printf("%s\n", [code UTF8String]);

    [pool release];
    return 0;
}

This program will generate (hopefully syntax error-free) Objective-C initialization code out of the provided property list which can be copy-pasted to a project and be used.

Edit: I just run the program on a stripped version of the plist file OP has provided (the original file was way too large, so I cut it a bit) and it generated the following code:

NSDictionary *dict = @{@"at": @[@"+43 1 ########", @"+43 ############", @"01 ########", @"00 $"], @"ar": @[@"+54## #### ####", @"## #### ####", @"00 $", @"18 ### $ "]};

To verify it was really valid, I pasted this into the middle of an int main() to a file called 'test.m', so I got this program:

#import <Foundation/Foundation.h>

int main()
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSDictionary *dict = @{@"at": @[@"+43 1 ########", @"+43 ############", @"0$
    NSLog(@"%@", dict);

    [pool release];
    return 0;
}

To verify, I run clang -o test test.m -lobjc -framework Foundation and surprise, surprise:

It worked.

Edit 2: I made this a command line utility, just to facilitate further work - who knows, this may be useful in the future. Plist2ObjC

Hope this helps.

0

What you need is Serializing a Property List

NSData* plistData = [source dataUsingEncoding:NSUTF8StringEncoding];
NSString *error;
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
NSLog( @"plist is %@", plist );
if(!plist){
        NSLog(@"Error: %@",error);
        [error release];
}

If you want to get it as a string, use this,

NSString *aString = [NSString stringWithFormat:@"%@", plist];

or else you can call NSString *aString = [plist description] to get the same as a string.

Source

Community
  • 1
  • 1
iDev
  • 23,310
  • 7
  • 60
  • 85
  • Yes but this just keeps the dictionary in the system. I want a code format of the dictionary. – Snowman Oct 24 '12 at 18:18
  • Do you mean you want to get the whole things as a text/string? – iDev Oct 24 '12 at 18:22
  • I just want to convert it to code format so I can have an editable NSDictionary in one of my methods, like this: http://pastebin.com/adNADRzU – Snowman Oct 24 '12 at 18:23
  • @mohabitar So basically you want to **generate Objective-C code that results in you having an NSDictionary literal with the same contents as the file you gave us a link to,** right? –  Oct 24 '12 at 18:47
  • @mohabitar wait a bit, I'll update my answer with the necessary info. –  Oct 24 '12 at 18:51
  • @mohabitar, I have updated my answer. Check if that is what you wanted. – iDev Oct 24 '12 at 18:54
  • @ACB One. This will give the old-style (OpenStep) representation of the propertly list, which is not what OP is looking for. Two, this won't generate valid Objective-C code (because of its format and the lack of an initialization statement). Three, `-description` is not to be relied on, it can change in future revisions of Foundation. –  Oct 24 '12 at 18:58
  • Can you please explain why 'this wont generate valid Objective-C code'? I didnt quite get it. As far as I know, this will generate a string in NSDictionary format which we normally used to display in console. – iDev Oct 24 '12 at 19:01
  • @ACB Yes, but as I said, that is the old OpenStep format, which you can't use directly for creating object literals, because it's not Objective-C code, it's just similar. –  Oct 24 '12 at 19:02
  • It is true that it is the earlier format, but [NSString stringWithFormat:@"%@", plist]; will generate a valid string. I am not sure what you meant by Objective-C code. – iDev Oct 24 '12 at 19:07
  • @ACB OP wants to convert the contents of a given property list to Objective-C code which he can copy-paste and compile. –  Oct 24 '12 at 19:09
  • Sorry, got confused with the question then. In that case you are right. – iDev Oct 24 '12 at 19:11
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18536/discussion-between-h2co3-and-acb) –  Oct 24 '12 at 19:21
0

In the latest macOS, there is a utility called plutil which can convert plists into a variety of formats. If you run it like this:

% plutil -convert objc -o output.m file.plist

Then it will generate a file called output.m which contains the objective-C initializer the matches the data in file.plist.

Chris Quenelle
  • 801
  • 4
  • 16