Objective-C, присвоить значение переменной строке plist - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть .plist файл, подобный следующему:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>key1</key>
    <string>variable1</string>
    <key>key2</key>
    <array>
        <string>foobar</string>
        <string>variable2</string>
    </array>
</dict>
</plist>

Мой код выглядит следующим образом:

NSString *variable1 = @"Hello";
NSString *variable2 = @"World!";

NSMutableDictionary *myDict = [NSMutableDictionary dictionaryWithContentsOfFile:@"/path/to/file.plist"];

NSLog(@"key1: %@", [myDict valueForKey:@"key1"]);
NSLog(@"key2: %@", [[myDict valueForKey:@"key2"] objectAtIndex:1]);

// outputs
// key1: variable1
// key2: variable2

То, что я надеюсь сделать, это иметь variable1и variable2 в файле .plist используйте variable1 и variable2 из кода (без особого указания в коде), поэтому значения из .plist в итоге будут Hello для variable1 иWorld! для variable2.

Очевидно, что назначить их так можно:

[myDict setObject:variable1 forKey:@"key1"];

Именно этого я и стараюсь избегать . Очевидно, что «переменные» - это просто строки в .plist, и obj-c не думает присваивать им значения переменных из кода. Итак, вопрос в том, могу ли я присвоить им значения из кода (например, <variable>variable1</variable>), или как-то не сделать их строками? Или, может быть, это просто невозможно.

Примечание: я не программист, поэтому, пожалуйста, имейте это в виду, спасибо.

1 Ответ

1 голос
/ 10 ноября 2019

Таким образом, вопрос в том, могу ли я присвоить им значения из кода (например, variable1) или как-то не сделать их строками?

Много способов, но ...

Примечание: я не программист, поэтому, пожалуйста, имейте это в виду, спасибо.

, что создает очевидные проблемы! Мы не знаем, сколько вы на самом деле знаете, вы не представили никаких попыток выполнить фактическую замену и т. Д. Однако вы делаете хорошее наблюдение:

Очевидно, что «переменные» - это просто строкив .plist и obj-c не думает присваивать им значения переменных из кода.

Многие начинающие, а некоторые нет, путают разницу между символами. последовательность variable1, используемая в качестве имени для переменной, и та же последовательность, что и в качестве значения для строки - вы правильно определили, что это разные вещи.

Давайтепосмотрим, сможем ли мы помочь вам без длинного урока по разработке программ. Во-первых, мы остановимся на использовании вами plist для вашего словаря (позже, учитывая ваше предложение <variable>variable1</variable>, вы можете рассмотреть возможность использования своего собственного XML).

Во-вторых, мы сделаем предположение, что когда«переменная» используется в качестве значения в вашем словаре, оно всегда будет значением целом , а не его частью, например, вы никогда не получите что-то вроде <key>key1</key> <string>The value of the variable is: variable1</string> и ожидаете замены variable1.

Мы начнем с изменения вашего кода для чтения plist из пакета приложения и использования современного синтаксиса Objective C для поиска значений словаря и массива:

NSURL *sampleURL = [NSBundle.mainBundle URLForResource:@"sampleDictionary" withExtension:@"plist"];
NSMutableDictionary *myDict = [NSMutableDictionary dictionaryWithContentsOfURL:sampleURL];

NSLog(@"key1: %@", myDict[@"key1"]);    // dictionary lookup
NSLog(@"key2: %@", myDict[@"key2"][1]); // dictionary + array lookup

Файл sampleDicitonary.plist имеетбыл добавлен в дополнение и содержит ваш список. Это выводит:

key1: variable1
key2: variable2

, как это делает ваш код.

Теперь вместо объявления двух переменных, variable1 и variable2, вы можете использовать словарь, в котором ключ являетсяимя переменной:

NSDictionary *variables = @{ @"variable1": @"Hello",
                             @"variable2": @"World!"
                           };

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

  • Поиск ключа в словаре, например, myDict[@"key1"] выше, возвращает nil, если ключ не существует в словаре;
  • Выражение <expr1> ?: <expr2> оценивается как значение <expr1>, если значение не равно nil, другие - как <expr2> (Это сокращение условного выражения - которое вы можетеищите.)

Так что, если мы присвоим результат индексации вашего plist переменной:

NSString *rawKeyValue = myDict[@"key1"];

, а затем ищем это значение в нашем словаре variables:

NSString *substitutedValue = variables[rawKeyValue];

тогда, если rawKeyValue имеет значение одного из имен ваших "переменных" (variable1, variable2), тогда substitutedValue будет соответствующим значением (Hello, World!). Если rawKeyValue не является именем переменной, тогда substitutedValue будет nil ...

Но вам не нужно nil во втором случае, вам нужно значение rawKeyValue иВы можете получить это, используя оператор ?:, который дает замену первого NSLog() из:

NSString *rawKeyValue = myDict[@"key1"];
NSString *substitutedValue = variables[rawKeyValue] ?? rawKeyValue;
NSLog(@"key1: %@", substitutedValue);

, который выдаст:

key1: Hello

Выполнение этих дополнительных шагов длякаждый поиск повторяется и утомителен, и в программировании есть решение: определить метод для его инкапсуляции и избегать использования промежуточных переменных. Вот возможный метод:

- (NSString *)substitute:(NSDictionary *)variables in:(NSString *)value
{
   return variables[value] ?: value;
}

и с этим определенным первым NSLog становится:

NSLog(@"key1: %@", [self substitute:variables in:myDict[@"key1"]]);

Надежда, которая помогает и помогает вам начать. Но потратьте время на изучение программирования правильно, если вы собираетесь писать программы!

...