NSDictionary`描述`格式化问题 - 将结构视为char数据

Hot*_*cks 8 iphone formatting objective-c ios

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

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

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

例如,而不是具有如下输出:

theChildren = (
                  {
                      "@meta.type" = "ns3:location";
                      "childNumber" = 0;
                      ...
Run Code Online (Sandbox Code Playgroud)

看起来像:

theChildren = "( \n\t\t {\n\t  \"@meta.type\" = \"ns3:location\";\n\t   \"childNumber\" = 0;
...
Run Code Online (Sandbox Code Playgroud)

任何人都可以提出改变这种行为的方法吗?

FWIW,我NSDictionary description在NSMutableString中累积描述字符串(主要包含来自调用的结果的数据),然后NSString stringFromString在退出处执行(虽然我不知道这会做什么).

添加

我想我找到了NSDictionary写入中的答案(尚未检查):

讨论

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

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

If the object responds to descriptionWithLocale:indent:, that
Run Code Online (Sandbox Code Playgroud)

调用方法以获取对象的字符串表示形式.

If the object responds to descriptionWithLocale:, that method is
Run Code Online (Sandbox Code Playgroud)

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

If none of the above conditions is met, the object’s string
Run Code Online (Sandbox Code Playgroud)

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

更新

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

更新9/23

有趣的是,如果我使我的类成为NSArray的子​​类,那么NSDictionary会调用descriptionWithLocale:indent:并且它正确格式化.听起来像NSDictionary是"作弊"和测试isKindOfClass而不是respondsToSelector,或者只是对非NS的东西有偏见.

然而,在获取许多我不想模仿的行为以及携带额外的未使用数据方面,必须继承NSArray是一种丑陋.

等等

另一种选择是将转义后的字符串转换回原始字符串.这需要一个31线过程来处理的基础知识(\n,\t,\",和\\).从好的方面来说,我不需要继承NSArray.主要缺点是必须在任何可以显示我的类的NSLog调用中插入此例程.另一个小的缺点是逃脱的字符串上写着我无法消除的引号字符,但这几乎不可察觉.

现在得到#ifdefed - 不确定我会选择哪个.

NSG*_*God 5

这是OS X 10.5+版本中引入的一个与安全相关的精彩"功能" syslog().

正如苹果工程师在这篇文章中解释的那样:谁在Leopard上破坏了NSLog?,

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

嵌入在消息字符串中的换行符和其他不可打印字符以替代格式打印.这可以防止有人使用不可打印的字符在输出文件中构造误导性日志消息.换行符打印为"\n",标签打印为"\ t".使用插入符号("^")表示打印其他控制字符,例如"^ M"用于回车.

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

Chris Kane Cocoa Frameworks,Apple

有关详情man syslog,请参阅.


Hot*_*cks 2

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

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

不过,就获取许多我不想模仿的行为以及携带额外未使用的数据而言,必须对 NSArray 进行子类化有点丑陋。ETC

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

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