Преобразование списков свойств в литералы Objective-C

Я не уверен, возможно ли это, но я видел, как люди делают сумасшедшие вещи с помощью регулярных выражений и других инструментов.

Я хочу преобразовать этот список в литералы Objective-C:

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

</dict>

конвертировано в:

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

Можно ли автоматизировать такое преобразование? Этот парень сделал что-то похожее: он проанализировал список PHP в NSDictionary с помощью VIM.

3 ответа

Решение

У Plist нет отдельного "формата" для использования в коде (этот вопрос не имеет смысла как есть). Вы либо хотите 1. сгенерировать код Objective-C, который инициализирует словарь с этими значениями, либо 2. инициализировать словарь, используя файл, для которого вы можете написать

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

Редактировать: поэтому вы хотите сгенерировать код Objective-C, который в свою очередь будет воспроизводить тот же словарь. Для этого вам необходимо заново распечатать содержимое словаря в отформатированном виде. Вы можете написать такую ​​программу:

#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;
}

Эта программа будет генерировать (возможно, без синтаксического ошибки) код инициализации Objective-C из предоставленного списка свойств, который можно скопировать в проект и использовать.

Редактировать: я просто запускаю программу на урезанной версии файла plist, предоставленного OP (исходный файл был слишком большим, поэтому я немного его обрезал), и он сгенерировал следующий код:

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

Чтобы убедиться, что это действительно так, я вставил это в середину int main() в файл с именем "test.m", поэтому я получил эту программу:

#import <Foundation/Foundation.h>

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

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

    [pool release];
    return 0;
}

Чтобы проверить, я бегу clang -o test test.m -lobjc -framework Foundation и сюрприз, сюрприз

Это сработало.

Изменить 2: я сделал это утилита командной строки, просто чтобы облегчить дальнейшую работу - кто знает, это может быть полезно в будущем. Plist2ObjC

Надеюсь это поможет.

В последней версии macOS есть утилита plutil, которая может преобразовывать списки в различные форматы. Если запустить так:

% plutil -convert objc -o output.m файл.plist

Затем он сгенерирует файл с именем output.m, который содержит инициализатор Objective-C, соответствующий данным в файле.plist.

Что вам нужно, это сериализация списка свойств

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];
}

Если вы хотите получить его как строку, используйте это,

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

или вы можете позвонить NSString *aString = [plist description] чтобы получить то же самое, что и строка.

Источник

Другие вопросы по тегам