iOS/Mac OS 调试信息输出(二)

8 Comments

NSLog,没那么简单

在前一篇《iOS/Mac OS 调试信息输出(一)》中介绍了输出调试信息的方法。现在讲主角:NSLog。

1.NSLog工作流程

前面已经说过我们很多时候都只是讲NSLog当做是printf,比printf好就好在:1. 自动添加了换行符;2. 在信息头还添加了一些其他更易于阅读和标示的信息,如“2011-03-12 20:18:34.000 Test14[40871:903]”。但其实NSLog更重要的功能是Log功能。看了下面这幅图你也许久明白了NSLog的工作原理了。

NSLog工作流程图

所以从图中可以看出NSLog的工作主要是分为:1. 输出信息到终端,2. 输出信息到System Log中去。

一般开发的时候程序都是从Xcode中启动,所以这个时候NSLog就具有打印信息到终端的能力就像printf一样(说fprintf(stderr, ….) 更合适一点)。而且很自然也就认为NSLog只是用来打印这些调试信息用的。

但是当程序不是从xcode或者ternimal启动等时,因为stderr不是被定向到标准终端这个时候NSLog的功能就是把信息输入到System Log中去。如果这个时候你也用的stderr输入信息,这个时候stderr会被定向到System Log中去。

2. Log结构

我之前说过Log信息是有level之分的,完整的Log是包含很多key-value形式的其他信息的,下面我们看一个通过NSLog输入到System Log的Log实例:
{
ASLMessageID = 3827200;
“CFLog Local Time” = “2011-03-12 16:31:02.592″;
“CFLog Thread” = 903;
Facility = “com.apple.console”;
GID = 20;
Host = “Xu-Benyangs-MacBook-Pro”;
Level = 4;
Message = “Hello World!”;
PID = 27692;
ReadUID = 501;
Sender = Test14;
Time = 1299918662;
TimeNanoSec = 593334000;
UID = 501;
}

其中我们比较关注的有这几项:

  1. Facility:用一个反链接形式字符串标示发送Log的来源,比如NSLog内部就使用的是com.apple.console
  2. Level: 等级,NSLog的等级是4,也就是Warnning,根据之前我们多/private/etc/syslog.conf 查看,只要是在Notice(5)之上的Log都可以被记录到/private/var/system.log中去。所以你调用一个NSLog你就可以去看看你的system.log文件
  3. Message: 就是消息本省
  4. Sender:你的应用程序名称
所以从上面信息可以看出NSLog的Log是:Facility=“com.apple.console”; Level=4(每一条NSLog都当做是一个Warning Log)的信息。而顺便提一下stderr如果被定向到System Log,那么是:Facility=“user”, Level=5(每一条是当做一个Notice的Log)。

3. 查看Log的方法

那么NSLog既然主要作用是用来发送System Log的,那么如何可以方便查看这些Log呢?特别是哪些搞测试和调程序的同学来讲,看Log是做常见的事情,所以这里给出在Mac和iOS下在没有源代码或者脱离了Xcode运行环境怎么看Log的方法。

Mac

  1. 如果你的systemlog.conf配置正确,就可以直接去查看这个文件 /private/var/log/system.log
  2. 打开/Applications/Utilities/Console这个程序,在Log List中选Console Messages就可以查看所有程序的NSLog打印出来的信息了。如图:

如图所示,Console中也提供了查看system.log的快捷方式。这里可能对你造成困惑,为什么有了system.log还有一个Console Messages。其实说白了Console Messages只是讲system log 中facility为“com.apple.console”的都筛选出来了,所以你就姑且可以把Console Messages中的信息认识全部是NSLog产生的。但是其实如果你自己发送一个facility=“com.apple.console”的日志,同样会出现在Console Messages中。

iOS
在真机上调试程序的时候打开Xcode 中的Oganizer, 然后在你当前的device下选取Console就可以看到这个Device的System Log了,如图。


这里我用的是xcode 4,所以界面和你的也许会不一样。

4. 程序员使用NSLog注意事项

在了解了NSLog的工作原理之后,你还敢像只是用printf那样使用NSLog了吗?我可以很负责人的告诉你虽然苹果的设备硬件条件都很牛B,但是NSLog还是是一件非常expensive的事情,主要体现在这两点:
  1. NSLog在打印信息的同时要发送日志,效率低
  2. 程序一些调试信息通过NSLog发送到System Log之后,很容易被其他人查看到,对你程序的安全性造成了直接的威胁。除了通过xcode的oganizer可以查看console,在iPhone上有一个叫ConsoleLog的程序可以查看你的这些日志(http://itunes.apple.com/us/app/consolelog/id415116252?mt=8)。
所以综合这些因素,我们应该在程序release的时候尽量去掉NSLog,但是如果程序大了一个一个去删NSLog似乎也不现实。于是网上就有不少牛人提供了不少的解决方案。推荐一篇著名的Cocoa Is My Girlfriend的Dropping NSLog in Release Build” : http://www.cimgf.com/2009/01/24/dropping-nslog-in-release-builds/ .

最后,感谢CamScanner帮我把手绘直接扫描成电子版。

 

8 Comments (+add yours?)

  1. atatstone
    三 14, 2011 @ 10:39:56

    这笔迹。。真清秀

    回复

    • Near
      三 17, 2011 @ 20:04:52

      这也是清秀?

  2. atatstone
    三 14, 2011 @ 10:40:45

    奇怪啊,明明我是沙发,为啥显示“2 comments”?

    回复

  3. Kim
    三 15, 2011 @ 11:01:35

    下了一个晚上的xcode 4 看博主的xcode 4中的organizer还挺犀利

    回复

  4. ailicec
    八 02, 2011 @ 23:10:34

    你好,我刚开始在Xcode中调试程序,
    现在使用的是 Xcode 4.1 (Lion上),有个很奇怪的情况,就是程序中使用了 NSLog 之后,应该打印出我写的信息,但是我找不到哪里去看这个信息,已经查找了 Xcode 的 Debug 区域,没有信息,在 console 中也没有相关信息。在网上搜来搜去,都没有相关的问题,所以我想可能是我自己还不知道 Xcode 该如何使用⋯⋯ [但是看了你的文章,觉得我是用了 NSLog,应该会在系统 console 中有信息的啊⋯⋯还是没看到⋯⋯],只要留言咨询了:)

    回复

    • Near
      八 12, 2011 @ 10:34:47

      你看以下你的console 的output设置正确没有。。。。我估计你是选了debugger output了。。。

Leave a Reply

使用新浪微博登录
  • RSS
  • Twitter
  • Buzz
  • LinkedIn
  • Flickr