【问题标题】:NSDictionary `description` formatting problem -- treats structure like char dataNSDictionary `description` 格式化问题——将结构视为 char 数据
【发布时间】:2011-09-22 21:23:01
【问题描述】:

我有一个自定义类(它在概念上类似于 NSArray,并且希望是格式化​​的外观),它有一个 description 格式化程序。

当格​​式化程序的输出本身被打印(NSLog)时,它看起来很好,但是当它作为 NSDictionary description 的元素包含时,NSDictionary 格式化程序似乎决定它是一个字符串,而不是结构定义,将其括在引号中,并转义字符串中的所有控制字符。

当然,对于标准的 NSArray,它不会这样做,所以我想知道它是如何决定以一种方式处理字符串而不是另一种方式的。

例如,而不是输出看起来像:

theChildren = (
                  {
                      "@meta.type" = "ns3:location";
                      "childNumber" = 0;
                      ...

看起来像:

theChildren = "( \n\t\t {\n\t  \"@meta.type\" = \"ns3:location\";\n\t   \"childNumber\" = 0;
...

谁能提出改变这种行为的方法?

FWIW,我在 NSMutableString 中累积描述字符串(数据主要由调用 NSDictionary description 的结果组成),然后在出口处执行 NSString stringFromString(尽管我不知道它有什么作用)。

添加

我想我在 NSDictionary 的文章中找到了答案(尚未检查):

讨论

返回的 NSString 对象包含 字典的每个条目。 descriptionWithLocale:缩进: 获取给定键或值的字符串表示形式,如下所示:

If the object is an NSString object, it is used as is.

If the object responds to descriptionWithLocale:indent:, that

调用方法来获取对象的字符串表示。

If the object responds to descriptionWithLocale:, that method is

调用以获取对象的字符串表示形式。

If none of the above conditions is met, the object’s string

表示是通过调用其描述方法获得的。

更新

好吧,事实证明他们在撒谎。我实现了 descriptionWithLocale:indent: 并且它永远不会被调用。

9 月 23 日更新

有趣的是,如果我让我的类成为 NSArray 的子类,那么 NSDictionary 会调用 descriptionWithLocale:indent: 并且它的格式正确。听起来 NSDictionary 是在“作弊”和测试 isKindOfClass 而不是 respondsToSelector,否则只是对非 NS 的东西有偏见。

但是,在获取许多我不想模仿的行为以及携带额外未使用的数据方面,必须将 NSArray 子类化有点难看。

另一种选择是将转义的字符串转换回其原始字符串。这需要一个 31 行的过程来处理基础知识(\n\t\"\\)。好处是我不需要继承 NSArray。主要的缺点是这个例程必须插入​​到任何可以显示我的类的 NSLog 调用中。另一个小缺点是转义的字符串被我无法消除的引号字符包装,但这几乎不引人注意。

现在知道#ifdefed -- 不确定我会选择哪个。

【问题讨论】:

  • 您应该将其添加为答案!
  • 不幸的是它不是答案。
  • 是的,你可以回答你自己的问题。当您在询问时知道答案时通常不是很好的形式,但如果您在等待时发现答案 - 请继续添加!
  • @And 为什么它不是好的形式? Jeff Atwood 和 Meta 上的大多数选民都同意回答自己的问题(即使是立即回答)不是问题;例如,请参阅 thisthis
  • @Daniel 要么是 Cocoa (Touch) 错误,要么是文档错误。 File a radar.

标签: iphone objective-c ios formatting


【解决方案1】:

这是在 OS X 10.5+ 版本的syslog() 中引入的与安全相关的“功能”。

正如苹果工程师在这篇文章中解释的那样:Who broke NSLog on Leopard?

这就是syslog() 的行为。从手册页:

消息中嵌入的换行符和其他不可打印字符 字符串以另一种格式打印。这可以防止某人 使用不可打印字符构建误导性日志 输出文件中的消息。换行符打印为“\n”,制表符打印为 “\t”。其他控制字符使用插入符号 ("^") 打印 表示,例如“^M”表示回车。

NSLog() 写入的 ASL 子系统也是如此(至少在 豹)。将 XML 写入文件是一种合理的选择。

Chris Kane 可可框架,Apple

请参阅man syslog 了解更多信息。

【讨论】:

  • 那么“正常”的东西怎么能写出来呢?
【解决方案2】:

这个问题没有真正的答案(OS X 的“安全功能”似乎不会影响 iOS 控制台写入),但有以下两种解决方法:

#1: 有趣的是,如果我让我的类成为 NSArray 的子类,那么 NSDictionary 会调用 descriptionWithLocale:indent: 并且它的格式正确。听起来 NSDictionary 是“作弊”,测试 isKindOfClass 而不是 respondsToSelector,否则只是对非 NS 的东西有偏见。

但是,在获取许多我不想模仿的行为以及携带额外未使用的数据方面,必须将 NSArray 子类化有点难看。 等等

#2: 另一种选择是将转义字符串转换回其原始字符串。这需要一个 31 行的过程来处理基础知识(\n、\t、\" 和 \)。好处是我不需要继承 NSArray。主要的坏处是必须插入此例程在任何可以显示我的类的 NSLog 调用中。另一个小缺点是转义的字符串被我无法消除的引号字符包装,但这几乎不引人注意。

(接受这个答案,即使它不是“真正的”答案,因为否则我接受的百分比会受到影响。我猜我问了太多困难的问题。)

【讨论】:

  • 你能扩展点#1吗?如何将数组应用到序列化中?
  • @JonathanChiu -- 我不明白你的意思。 “申请”是什么意思?什么“序列化”?
  • 哦,对不起。我误读了你的问题。我自动假设您的问题与字典的 HTTP 发布有关,因为当我尝试序列化我的字典以进行发布时,我遇到了完全相同的格式问题。这是我的问题:stackoverflow.com/questions/8221607/…。我正在尝试将您的解决方案应用于我的问题,但我不确定如何。或许你会有一些见解?
  • 您通常不应该使用“描述”进行序列化。为此,您应该使用 JSON 生成器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2015-01-05
  • 1970-01-01
  • 2018-09-27
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
相关资源
最近更新 更多