Objective-C, 将变量值赋给 plist 字符串

Objective-C, Assign variable value to plist string

我有一个这样的 .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

我希望做的是让 .plist 文件中的 variable1variable2 使用代码中的 variable1variable2 (没有在代码中专门这样做),因此来自 .plist 的值对于 variable1 最终为 Hello,对于 variable2 最终为 World!

显然可以这样分配它们:

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

这正是我要避免的。很明显,"variables" 只是 .plist 中的字符串,obj-c 并没有考虑将代码中的变量值赋给它们。所以问题是我可以为它们分配代码中的值(如 <variable>variable1</variable>),还是不让它们成为字符串?或者这可能是不可能的。

注意:我不是程序员,所以请记住这一点,谢谢。

So the question is can I assign them the values from the code (like variable1), or somehow not make them strings?

很多方法,但是...

Note: I'm not a programmer, so please keep this in mind, thank you.

这带来了明显的挑战!我们不知道您实际知道多少,您也没有尝试进行实际的替换等。但是您确实做了很好的观察:

Clearly the "variables" are merely strings in the .plist and obj-c doesn't think to assign them the values of the variables from the code.

许多初学者和一些不是初学者的人混淆了用作变量 名称 的字符序列 variable1 和使用的相同序列之间的区别作为字符串的 value – 你正确地识别出它们是不同的东西。

让我们看看我们是否可以在没有关于程序设计的冗长课程的情况下帮助您。首先,我们将坚持使用 plist 作为字典(稍后根据您对 <variable>variable1</variable> 的建议,您可能希望考虑使用自己的 XML)。

其次,我们假设当 "variable" 在您的字典中用作值时,它将始终是 整个 值而不是其中的一部分,例如你永远不会有像 <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 已添加到地址并包含您的 plist。这输出:

key1: variable1
key2: variable2

就像您的代码一样。

现在不用声明两个变量 variable1variable2,您可以使用一个字典,其中键是变量名:

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

这表示与您的两个不同变量相同的信息,但重要的是变量名称只是 strings,而且您已经观察到您的 plist 包含字符串 - 所以现在我们有字符串替换而不是变量替换的问题。要进行字符串替换,我们使用:

  • 字典中的关键查找,例如上面的myDict[@"key1"],returns nil 如果key不在字典中;
  • 如果值不是 nil,则表达式 <expr1> ?: <expr2> 的计算结果为 <expr1>,其他情况下它的计算结果为 <expr2>(这是条件表达式 – 你可以查一下。)

因此,如果我们将索引到您的 plist 的结果分配给变量:

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

然后在我们的 variables 字典中查找该值:

NSString *substitutedValue = variables[rawKeyValue];

那么如果 rawKeyValue 的值是你的 "variables" (variable1, variable2) 的名称之一,那么 substitutedValue 将是相应的值(HelloWorld!)。如果 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"]]);

希望对您有所帮助并帮助您入门。但是如果你要写程序,一定要花时间好好学习编程!