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

时间:2011-09-22 21:23:02

标签: iphone objective-c ios formatting

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

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

当然,对于标准的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 - 不确定我会选择哪个。

2 个答案:

答案 0 :(得分:5)

这是一个与安全相关的精彩“功能”,已在OS {10.5}版syslog()中引入。

正如本文中的Apple工程师所解释的那样:Who broke NSLog on Leopard?

  

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

     
    
      

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

    
  
     

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

     

Chris Kane Cocoa Frameworks,Apple

有关详细信息,请参阅man syslog

答案 1 :(得分:2)

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

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

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

#2:另一种选择是将转义后的字符串转换回原始字符串。这需要一个31行程序来处理基础知识(\ n,\ t,\ t \,和\)。最重要的是我不需要子类化NSArray。主要缺点是必须插入此例程在任何可以显示我的类的NSLog调用中。另一个小的缺点是转义的字符串包含了我无法消除的引号字符,但这几乎不可察觉。

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