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

Posted

技术标签:

【中文标题】Objective-C,将变量值分配给 plist 字符串【英文标题】:Objective-C, Assign variable value to plist string 【发布时间】:2019-11-08 07:26:14 【问题描述】:

我有一个像这样的.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 最终成为Hellovariable1World!variable2

显然可以像这样分配它们:

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

这正是我想要避免的。显然,“变量”只是.plist 中的字符串,而 obj-c 并不认为将代码中的变量值分配给它们。所以问题是我可以为他们分配代码中的值(如&lt;variable&gt;variable1&lt;/variable&gt;),还是不让他们成为字符串?或者这可能是不可能的。

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

【问题讨论】:

可能在 info.plist 中写入不是一个好主意,而且它不起作用,因为您试图将字典写入 App 包中的 .plist 文件,该文件是只读的。因此,即使您以其他方式完成它,它也不会起作用,并且也会有更多的拒绝机会。顺便说一句,为什么只有 Info.Plist?我的意思是为什么你不能以其他方式拥有它,比如 NSUserDefault 和 SQLite @DhavalRaval:我实际上不想写信给应用程序.plist,而是使用.plist 作为应用程序使用的字典的模板。该应用程序也是一个内部工具,AppStore 中不提供。 【参考方案1】:

所以问题是我可以为它们分配代码中的值(如变量 1),还是不让它们成为字符串?

方法很多,但是...

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

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

显然,“变量”只是 .plist 中的字符串,而 obj-c 并不认为将代码中的变量值分配给它们。

许多初学者,以及一些不是初学者,混淆了用作变量名称的字符序列variable1与用作值 代表一个字符串——你正确地识别出这些是不同的东西。

让我们看看我们是否可以在不上冗长的程序设计课程的情况下帮助您。首先,我们将坚持使用 plist 作为您的字典(稍后根据您对 &lt;variable&gt;variable1&lt;/variable&gt; 的建议,您不妨考虑使用自己的 XML)。

其次,我们假设当“变量”用作字典中的值时,它始终是整个值,而不是它的一部分,例如你永远不会有像&lt;key&gt;key1&lt;/key&gt; &lt;string&gt;The value of the variable is: variable1&lt;/string&gt; 这样的东西并期望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!"
                           ;

这代表与您的两个不同变量相同的信息,但至关重要的是,变量名称只是 字符串,并且正如您已经观察到您的 plist 包含字符串 - 所以现在我们遇到了 字符串替换而不是变量替换。要进行我们使用的字符串替换:

字典中的键查找,例如上面的myDict[@"key1"],如果字典中不存在该键,则返回nil; 如果值不是nil,则表达式&lt;expr1&gt; ?: &lt;expr2&gt; 计算为&lt;expr1&gt; 的值,否则计算为&lt;expr2&gt;(这是条件表达式的缩写 –你可以查一下。)

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

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

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

NSString *substitutedValue = variables[rawKeyValue];

那么如果rawKeyValue 的值是您的“变量”名称之一(variable1variable2),那么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"]]);

希望对您有所帮助并帮助您入门。但是,如果您要编写程序,请花时间正确地学习编程!

【讨论】:

这是很好的信息,非常感谢您花时间解释它。

以上是关于Objective-C,将变量值分配给 plist 字符串的主要内容,如果未能解决你的问题,请参考以下文章

尝试将变量值分配给结构元素。起初变量有正确的值,但结构元素有垃圾值

如何将变量值“传递”给 JSON 动态对象?

将变量值从 JS 传递给 PHP

通过单击鼠标将变量值传递给java中的servlet

如何将变量值传递给julia中的宏?

如何将变量值传递给套接字字符串