如何使用NSLog调试iOS 8扩展?

93
- (void)viewDidLoad
{
    NSLog(@"%s", __func__);
    // ...
}
在iOS 8扩展的viewDidLoad中,NSLog在Xcode中没有输出。然而,在容器应用程序中,NSLog像往常一样工作。 我该如何从扩展中获取调试消息的输出?

我也遇到了这个问题。也许NSLog出了问题。目前我使用断点来调试值。但它们也非常不稳定。 - gallileo
我遇到了类似的问题,在Xcode中调试器从未附着并始终显示“等待附加”。不幸的是,我在谷歌上搜索没有找到有用的信息,并在Stack上发布了一个问题,但尚未得到答案。 - Alex Bollbach
16个回答

101
  1. 调试可以用于应用程序扩展。
  2. 它也适用于模拟器。
  3. 如果您的应用程序扩展在模拟器中崩溃,您可能会发现重新启动应用程序扩展并不容易。重新启动模拟器是一个快速解决方案。
  4. 调试应用程序扩展的步骤:

    1. 运行容器应用程序。 在此步骤中,Xcode将容器应用程序和应用程序扩展上传到设备或模拟器。

    2. 停止容器应用程序。 当您在模拟器中进行调试时,此步骤非常重要。 如果您不这样做,Xcode会告诉您模拟器正在使用中。

    3. 在Xcode中,按菜单 Debug -> Attach to Process -> By Process Identifer (PID) or Name...,输入应用程序扩展的标识符(例如com.abc.ContainerApp.MyExtension)开始调试。不要忘记设置断点。(2014年8月25日更新:您可以直接输入您的扩展名MyExtension。)

    4. 在设备或模拟器中打开您的应用程序扩展。


2014年8月23日更新:

我发现上面的调试步骤在Xcode 6 beta 6和iOS 8 SDK beta 5上的模拟器上效果不佳。

解决方法:

  1. 在模拟器中运行您的扩展程序。
  2. 选择菜单中 System 部分的"MyExtension(您的扩展名)",然后按 Xcode 菜单 Debug -> Attach to Process -> Choose。

断点有效。但我不知道为什么日志没有显示在输出窗口中。


9
到目前为止,我发现最简单的调试方法(并查看NSLog)是按照以下步骤进行:/// 1 /// 选择一个容器应用程序模式并运行它。/// 2 /// 一旦它启动和运行 - 切换回到XCode,(甚至不需要按停止按钮)选择扩展模式,然后按运行按钮。/// 3 /// 当提示选择要运行的应用程序时,请选择Today。/// 4 /// 现在断点和NSLog应该可以正常工作。 - interrupt
1
即使在今天,尤其是在崩溃之后,这仍然无法正常工作。这非常令人恼火,我不明白为什么修复起来如此困难。 - Cristi Băluță
3
我尝试使用上面更新的指南,对我很有用。然而,在第二步中,我没有使用我的扩展名,而是使用了“按进程标识符(PID)或名称...”,并输入了进程的pid。这神奇地允许我使用我的断点。 - tony.tc.leung
调试 > 通过PID或名称附加到进程:在调试导航器中的文本字段中输入进程名称,例如com.company.AppName.AppName-ExtensionName。 - TigerCoding
你有任何想法,如何使用Xamarin Studio做到这一点吗? - Johnykutty
显示剩余2条评论

49

如果您在模拟器下进入“调试”菜单 -> “打开系统日志...”,它对我有效。

从这里,您可以查看iPhone模拟器的所有日志(包括您的扩展日志)。

enter image description here


它将打开“~/Library/Logs/CoreSimulator/<DEVICE_IDENTIFIER>/system.log”,因此您可以轻松找到所有其他模拟器设备的日志,只需用模拟器设备ID替换<DEVICE_IDENTIFIER>即可。 - Hofi

33

NSLog 正常工作。

你没有在 Xcode 的调试区域看到日志是因为 Xcode 调试器没有附加到你的扩展上。扩展与其所包含的应用程序几乎完全独立。例如,它们有不同的包标识符,并且它们也是操作系统上的单独进程。

我成功地让 Xcode 附加到扩展上的经验是各种各样的。据说它似乎会自动附加,并在调试导航器中显示为 "等待附加",但从未附加过。

有时,我能够在 Xcode 中运行我的扩展目标:

enter image description here

然后选择要在哪个应用程序中运行我的扩展。在这种情况下,我会选择它推荐的 "Today",即通知中心。

enter image description here

然后它有时会将调试器附加到我的扩展上。请注意,此方法仅适用于物理设备。

如果它没有附加,则可以使用 @VinceYaun 的答案中的手动附加方法。

我还尝试了其他的附加方法,但成功率不高,而且它们似乎只是将来会修复的错误。

要查看日志消息,您需要在顶部菜单栏中选择 Window -> Devices 并选择您的设备。您可以从该窗口底部打开设备日志。如果您正在模拟器上测试,则可以使用 @BalestraPatrick 的答案

一些错误已经在 Beta 2 中得到修复,我的猜测是,当启动扩展时,调试器最终会自动附加。

更新:在iOS 8 Beta 4的发布说明中:

扩展功能

Beta 4中已修复问题

  • 有时从Xcode调试启动扩展会失败。
  • 当UI扩展被终止时,它会重新启动并且不会消失。
  • 有时您的共享或操作扩展可能会挂起。
  • 重新部署扩展可能会在通知中心中禁用它。

你尝试过对存储扩展采用相同的方法吗? - SRP-Achiever
它在Xcode 6 beta 2中对我无效,但Vince Yuan的答案有效。不幸的是,在Xcode 6 beta 3中,扩展调试根本不起作用。我没有找到解决这个问题的方法,可能我们必须等待下一个版本的发布。 - Darrarski
@Darrarski 我的回答还是Beta 1遗留的版本。通知一下,Beta 3已经发布了,你现在应该使用它。 - Andrew
@SantaClaus 很清楚。我的评论是为了告知我在 Xcode 6 beta 3 中没有一个给出的解决方案适用于我。看起来在这个版本中,扩展调试甚至更加失效。让我们希望下一个 beta 版本能够解决这个问题。 - Darrarski
我在beta 5中尝试了几个答案,但仍然显示“等待附加”。我还能尝试什么?如何查看NSLog消息?请帮忙,谢谢! - barfoon
3
在第四个测试版本(现在是第五个测试版本)中,我觉得那些错误似乎都没有被修复。 - matt

18
Xcode从不将我的调试器附加到扩展程序或显示NSLog消息。如果您手动将Xcode调试器附加到您的扩展进程,至少断点会像魅力一样工作:
Debug->Attach to process->Your extension name (mine was "com.example.MyExtensionApp.MyExtension")

5
我在这方面运气参半。 - Andrew
2
点赞,但不总是有效,希望苹果在未来的版本中可以自动附加调试器到扩展程序。 - Jing

16
  1. 创建您的扩展方案
  2. 运行方案
  3. 在对话框中选择容器应用程序
  4. 享受吧

对我来说有效 :)


这正是我所需要的。 - pob21
1
只有在运行容器应用程序时,NSLog才会起作用。如果您运行的是应用程序扩展而不是容器,则无法使用它。 - JaredH
这对我也起作用了。谢谢,Maciek Czarnik!上述解决方案对我没有起作用。我正在使用Xcode 8.1。 - plam4u

5

基于Michael的建议Apple的文档, 最终让我能够在调试区域看到日志的方法是:

在模拟器中构建并运行应用程序扩展,并在提示选择主机应用程序时选择要从中调用扩展的特定应用程序。 在我的情况下,我通过在PDF上拉出共享表单来从Safari启动我的Action扩展。

之前不起作用的是遵循其他人使用Today作为主机的建议,然后离开该应用程序并转到Safari调用我的扩展程序。 我甚至不再需要在运行扩展程序之前先运行包含应用程序。

来自Apple文档:

在您的扩展方案的Run阶段,您将指定一个主机应用程序作为可执行文件。通过访问该指定主机的UI来访问扩展程序,Xcode调试器会附加到扩展程序。


这应该是被接受的答案。使用这种工作流程可以启用断点和日志记录!谢谢。 - flymg

5

Xcode 8 能够调试扩展:

  1. 在停止按钮旁边的下拉框中选择扩展方案并运行它。
  2. 选择弹出的对话框中的父应用程序。

结果:断点和日志与平常一样工作。


2
在我的 Today 扩展中无法工作。出现 CLANG 错误:ld: library not found for -lRPush clang: error: linker command failed with exit code 1 (use -v to see invocation) - BadmintonCat
这是一个无关的错误。您正在尝试链接到一个缺失的库。请将 Liferay-Push 添加到您的目标中。 - Jano

1
一个对我有效的技巧(虽然有点丑陋)是在我的扩展中的底部角落放置一个虚拟的 UILabel。通常我称之为logLabel。然后可以更新该标签的文本以记录任何想要记录的日志语句。这种方法如果需要记录来自不同类实例的语句并不是很好。显然,它会使您的用户界面变得混乱。但是,如果您有一个相当简单的小部件,并且不介意轻微的UI混乱,那么这个技巧就能解决问题。我尝试了本讨论中提到的所有其他解决方案,但遗憾的是,它们都对我无效。

1
我的唯一调试方式是选择调试->通过PID或名称附加到进程,然后输入PID而不是扩展名。 您可以通过在设备上运行扩展程序,转到窗口->设备来查找PID。找到您的设备并查看控制台。当您看到扩展名时,它后面跟着5位数字。那就是PID 我还在扩展程序中放了一堆NSLog,以便找到PID。 这是在xCode 7上完成的。

1

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