Xcode附加到进程时不显示NSLog

35

我刚刚开始使用Apple Watch。我在"Five Minute Watchkit"找到了关于如何在模拟器中同时运行iOS应用程序和watch kit应用程序,并将两个进程都附加到LLDB调试器的说明。

我的做法是启动并退出iOS应用程序以在模拟器中安装当前版本。然后我切换到watchKit方案并启动它,这会在watch模拟器上显示我的手表应用程序UI。

然后我在模拟器中启动相应的iOS应用程序,然后在Xcode菜单中使用"attach to process"将调试器附加到正在运行的iOS应用程序。

这有效。我可以在watch kit InterfaceController或我的iOS应用程序中设置断点,调试器会在应该停止的地方中断。

然而,我没有在调试控制台中看到来自我的iOS应用程序的NSLog()语句。(我确实可以看到来自WatchKit扩展代码的日志语句。)如果我在我的iOS应用程序中设置一个断点,它确实会在应该停止的地方停止。我认为NSLog缺少控制台输出与附加到运行进程有某种关系,而不是从Xcode启动它,但我不知道具体原因。

(顺便说一句,在断点上附加一个调用NSLog的操作也无法显示,但"日志消息"调试器命令确实会显示。 有人有什么见解吗?)

编辑: iOS应用程序中的代码似乎并不重要。在我的情况下,它是一个与iOS应用程序故事板中的按钮相关联的极为简单的IBAction:

- (IBAction)buttonAction:(UIButton *)sender;
{
  NSLog(@"Button clicked on iPhone");
}

我可以在那个NSLog语句上设置断点。调试器会停在那一行,但是我在调试控制台中看不到日志语句。


1
你确定编译器能够执行到这里吗?哦,还请展示一些代码,那会很有帮助。 - LinusGeffarth
Linus,我确定。调试器在包含NSLog的行处中断。只是日志语句没有显示到控制台。 - Duncan C
2
第三次,调试器在问题所在的行处停止了断点。我绝对、百分之百地确定连接是正确的。如果我使用Xcode中的⌘R启动iOS应用程序,日志语句就会起作用。只有当我在模拟器中运行应用程序,然后附加到正在运行的进程时,我的NSLog语句才无法显示。 - Duncan C
2
将IBAction的参数类型更改为id只是在问题上挥舞一只死鸡,甚至不值得尝试。 - Duncan C
1
"挥舞一只死鸡解决问题" - Duncan C
显示剩余2条评论
8个回答

23
我可以使用一个简单的测试应用程序来重现这个问题,不需要WatchKit。该应用程序由一个NSTimer组成,每秒打印一次“Timer fired”。(这段代码是100%正确的;)。在手动附加到进程之后,日志中没有任何显示。
据我所知,NSLog输出到stderr,我猜调试器附加不会将stderr重定向到Xcode终端。
如果您愿意使用控制台应用程序或终端查看日志,您可以这样做。iOS8将模拟器日志存储在~/Library/Logs/CoreSimulator/<Device-UUID>中。在此目录中,您将找到一个system.log文件,其中包含所有的NSLog输出。
您可以在终端中查看它(使用catgreptail),或者在Console.app中打开它。

enter image description here


苹果确认在技术笔记TN2239:iOS调试魔法中(至少对于GDB)。

控制台输出

许多程序,甚至许多系统框架,都会将调试消息打印到stderr。此输出的目标最终由程序控制:它可以将stderr重定向到任何选择的目标。然而,在大多数情况下,程序不会重定向stderr,因此输出将进入从启动环境中继承的默认目标。这通常是以下之一:

  • 如果您像普通用户一样启动GUI应用程序,则系统会将stderr上打印的任何消息重定向到系统日志。您可以使用前面描述的技术查看这些消息。
  • 如果您在Xcode内运行程序,则可以在Xcode的调试器控制台窗口中看到其stderr输出(从“运行”菜单中选择“控制台”菜单项即可查看此窗口)。

附加到运行中的程序(使用Xcode的“附加到进程”菜单或GDB中的attach命令)不会自动将程序的stderr连接到您的GDB窗口。您可以使用Technical Note TN2030,“GDB for MacsBug Veterans”中“连接后查看stdout和stderr”部分中描述的技巧在GDB内完成此操作。

提到的TN2030已不再他们的服务器上可用(mirror)。它展示了如何将stdout和stderr重定向到Xcode控制台。然而,由于shell tty不是LLDB的有效命令,它并没有太大帮助。但也许有一种不同的方法可以访问tty Xcodes控制台使用,因此我附上了该TN的重要部分。

Seeing stdout and stderr After Attaching

If you attach GDB to a process (as opposed to starting the process from within GDB), you won't be able to see anything that the process prints to stdout or stderr. Programs launched by the Finder typically have stdout and stderr connected to "/dev/console", so the information they print goes to the console. You can view this by launching the Console application (in the Utilities folder), however, it's inconvenient to have to look in a separate window. Another alternative is to connect the process's stdout or stderr to the terminal device for GDB's Terminal window. Listing 9 shows how to do this.

Listing 9. Connecting stdout and stderr to GDB's terminal device.

(gdb) attach 795
[... output omitted ...]
(gdb) call (void) DebugPrintMenuList()
 No output )-:

 Close the stdout and stderr file descriptors.
(gdb) call (void) close(1)
(gdb) call (void) close(2)

 Determine the name of the terminal device for GDB itself.
(gdb) shell tty
/dev/ttyp1

 Reopen stdout and stderr, but connected to GDB's terminal.
 The function results should be 1 and 2; if not, something
 is horribly wrong.
(gdb) call (int) open("/dev/ttyp1", 2, 0)
$1 = 1
(gdb) call (int) open("/dev/ttyp1", 2, 0)
$2 = 2

 Try the DebugPrintMenuList again.
(gdb) call (void) DebugPrintMenuList()
 Yay output!
Index MenuRef     ID  Title
----- ---------- ---- -----
<regular menus>
00001 0x767725D3 -21629 Ed
00002 0x76772627 1128 <Apple>
00003 0x767726CF 1129 File
00004 0x76772567 1130 Edit
[... remaining output omitted ...]

8
如果必须的话,我可以在控制台查看我的日志输出,但这样很糟糕。控制台非常嘈杂。系统进程不断向控制台发布对我来说毫无意义的信息。此外,Xcode调试控制台就是为此而设计的。它应该显示正在运行的程序的输出。启动应用程序是一个多步骤的过程:关闭watch应用程序、iOS应用程序,构建并运行iOS应用程序,然后关闭它,打开watch应用程序,在模拟器中启动iOS应用程序,将调试器附加到iOS应用程序。说实话,这很麻烦。 - Duncan C
MacsBug?!? 哦,天哪,那可是很久以前的事了。那时候 Mac 还使用 68000 系列处理器。我在 80 年代末和 90 年代使用 MacsBug 在我的 Mac II 上。 - Duncan C
我应该在FMW帖子中添加一条关于这个的注释。 :-) - bgilham
我想补充一点,就是像上面提到的那样,使用grep过滤很容易找到你的调试信息,这样你就不会有控制台干扰了。 - El Tea
这是一个真正令人困惑的问题,我已经在整个早上搜索互联网了。每一个解释都会引发完全无关的讨论。到目前为止,这是唯一相关的答案。谢谢! - Joey Carson

13

除了Filipp Keks的回答之外,这里提供一个更加简单易懂的视觉化方法。

按照以下步骤:

  1. 将设备插入电脑并打开Xcode

  2. 选择菜单栏中的“窗口”->“设备”

  3. 在左侧的“DEVICES”栏下选择设备

  4. 点击右边面板底部左侧的向上三角形以查看设备控制台

  5. 点击右下方的向下箭头将控制台保存为文件

以下是Xcode 7.3.1中的“设备”窗口截图。

enter image description here


我批准它对于我的Xcode 8.3.3也是同样的工作方式。必须记住,这是一个完整的调试日志,因此所有的应用程序和服务都会显示在那里,你需要找到属于你的进程的部分。 - sunsetjunks
如果你能过滤这些日志,那就更“简单”了。但是目前(xcode 9.2)在UI上无法做到这一点(至少在实时会话中)。不管怎样,我发现了一个github项目deviceconsole,它可以在shell中完成相同的操作,允许你按照应该的方式进行过滤(有点不稳定,经常崩溃:( )。有没有人知道更好的项目? - itMaxence

8
使用Xcode Version 7.2和iOS 9.2等版本,我发现以下操作有效:
  1. 关闭手机应用和手表应用
  2. 选择手表扩展的目标并按下Cmd+R(编译和运行)
  3. 选择电话目标并按下Ctrl+Cmd+R(无需构建即可运行)
在我的情况下,我在它们各自的模拟器中运行了两个应用程序,并获得了两者的NSLog输出。我不需要单独附加。希望这能有所帮助。

我得试一下这个。感谢您在一个相当老的帖子上发布。 - Duncan C
2
当我这样做时,它会停止我的手表应用程序并使手表返回主屏幕。 - Saviz

3

https://developer.apple.com/library/ios/qa/qa1747/_index.html

  1. 将设备插入电脑并打开Xcode

  2. 点击菜单栏中的“窗口(Window)” -> “设备(Devices)”

  3. 在左侧栏的“DEVICES”部分选择需要查看的设备

  4. 要查看设备控制台,请单击右侧面板底部左侧的上三角

  5. 单击右下角的向下箭头可将控制台保存为文件


0

当您的配置文件设置为AdHoc或Distribution时,Xcode不会显示日志,您需要将其设置为开发模式以查看日志


0

这可能无法解决显示NSLog消息的问题,但在调试后台启动的应用程序时可能会有所帮助。

您可以使用允许您记录消息的断点功能。 思路是:

  • 创建一个断点,并选中“评估操作后自动继续”
  • 添加“日志消息”操作(您还可以使用表达式并打印出值,例如:“日志消息@variable@”)
  • 使用预期的进程名称附加调试器(XCode将等待进程启动)
  • 触发应用程序启动。

致谢和详细信息: https://fluffy.es/how-to-debug-app-which-got-launched-push-notification/


-1
我通过这个问题 (Xcode console empty after attaching to process) 来到了这里,那个问题现在已经关闭了。
我的问题是,在 Xcode 中调试控制台没有显示任何内容(只有一个空白的白色框)。
对我来说解决方案是在底部切换 "变量视图" 和实际的调试控制台之间的微小切换。

enter image description here


-2
在我的情况下,设置自动查看 NSLog,之前根本不显示。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接