概述

假如在查看源代码过错的根本原因不是很明显,那么在单步履行代码时观察变量的改变有助于发现过错产生的方位,以便找到或许的原因。

Xcode 调试器供给了几种办法来单步调试代码和查看变量。您能够从断点精确操控代码的履行,根据需要进入和退出调用的函数以确定过错产生的方位。您能够在单步履行代码时监控变量,或暂停履行以更细心地查看它们。

当您的应用程序在过错产生之前处于没问题的状况,在您认为过错或许行将产生的点处开始您的查询。

在调试器中单步履行代码

当您运转应用程序时,调试器会在遇到的第一个断点处暂停,而且默许情况下会更新显现以显现调试导航器、源代码编辑器、调试栏、变量查看器和操控台。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

经过选择 Xcode > Preferences > Behaviors > Running,自定义 Xcode 在调试器中运转应用程序时显现的内容。

运用调试栏中的按钮来操控应用程序的履行。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

– 从暂停方位持续正常履行,直到应用程序在下一个断点处停止,并运用 Continue 按钮。

  • 运用暂停按钮暂停应用程序而不设置断点。应用程序运转时,持续按钮变为暂停按钮。

  • 运用 Step Over 按钮履行相同功能中的下一条指令。也就是该办法的另外一句代码,假如这句代码是调用一个办法,不跳进办法,而是履行当时办法的下一条句子。

  • 运用 Step Into 按钮履行下一条指令。假如下一条指令在另一个办法或函数中,则每次单击 Step Into 按钮时,调试器都会跳转到该函数并持续履行它。

  • 运用 Step Into 后,单击 Step Out 按钮跳过函数的其余部分并回来到调用函数或办法中的下一条指令。

当您逐步浏览您的应用程序时,查看与您的过错相关的变量并注意意外值。

查看代码中的变量值和变量查看器

当您的应用程序在断点处暂停时,将鼠标悬停在源代码中的变量上以查看其当时值。假如变量是无法以文本形式表达的图画或其他类型,请单击右上角的“快速查看”按钮以查看变量的预览。单击打印描绘按钮以在操控台中打印目标的描绘。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

变量查看器列出了当时履行上下文中可用的变量。从查看器左下方的选择器中选择要查看的变量规模:auto自动变量、部分或一切变量、寄存器、全局变量和静态变量。运用过滤器字段查找与模式匹配的变量。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

假如适用,每个变量都会显现变量类型、值和指针方位的扼要摘要。变量查看器运用 lldb 指令帧变量生成它显现的摘要。假如变量的摘要不可用或仅显现内存指针,请参阅下面的操控台中的评价表达式部分,了解更多查看变量的办法。

单击显现三角形以探索类和结构的实例变量,或其他数据类型的内部结构。选择一个变量并单击“快速查看”按钮以查看变量的预览,单击“打印描绘”按钮以在操控台中打印目标的描绘。

###请参阅调用仓库和导航相关代码

当调试器在断点处暂停时,它会在调试导航器中显现当时活动线程和当时调用仓库,并杰出显现断点。调用仓库表明导致当时断点的函数或办法调用的关系。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

ios调试技巧(4)  通过在调试器中单步调试源代码时观察变量的变化来找出错误的原因。

假如您怀疑您的过错在调用函数中,请在调用仓库中选择一行。调用函数或许会过错地更改实例变量,或许或许在参数中传递了不正确的值。假如源代码在项目中可用,调试器会在变量查看器中显现该点的源代码和相关变量。不然,调试器会显现所选行的汇编代码。此时查看变量是否存在意外值。

选择一个线程以打开或折叠该线程的调用仓库视图。在调用仓库中为线程选择一行以查看源代码和变量。

在操控台中履行表达式

要查看比 变量查看器中显现更多的变量或许信息,或许要在调试会话中间改变 变量的值,请运用操控台直接与调试器交互。

运用帧变量或缩短的别号 v 打印当时仓库帧中的变量值。


(lldb) v self.fruitList.title
(String) self.fruitList.title = "Healthy Fruit”
(lldb) v self.listData[0]
(String) [0] = “Banana"

帧变量指令仅回来当时内存中的内容而且不核算表达式,因而假如您尝试打印更多内容,它会回来过错。例如,它不会打印函数或办法调用、@Published 变量或核算变量。


(lldb) v fruitList.fruit(at: indexPath)
error: no variable named 'fruitList' found in this frame
error: no variable named 'indexPath)' found in this frame
(lldb) v self.fruitList.calculatedFruitCount
error: "calculatedFruitCount" is not a member of "(Debugger_Demo.FruitList) self.fruitList”

运用表达式指令或别号 expr 或 p 核算表达式并在操控台中打印成果。


(lldb) p self.fruitList.calculatedFruitCount
(Int) $R18 = 9
(lldb) p fruitList.fruit(at: indexPath)
(Debugger_Demo.FruitItem) $R20 = 0x00006000013dcc90 (fruitName = "Strawberry", fruitDescription = "Small red berry with seeds on the outside.”)
(lldb) expr fruit.fruitName
(String) $R14 = "Strawberry"
(lldb) p fruit.fruitName == "Peach"
(Bool) $R16 = false

p 指令 先编译代码然后评价表达式,因而它处理函数调用和核算变量。运用 p 供给的引证作为其他表达式的一部分。


(lldb) p fruit.fruitName
(String) $R2 = "Banana"
(lldb) p fruit.fruitName
(String) $R6 = "Strawberry"
(lldb) p $R2 + ", " + $R6
(String) $R8 = "Banana, Strawberry"

关于某些类,运用 p 或许只显现一个内存指针方位,或许或许显现该类一切特点的完全打开视图,这或许是很多不必要的信息。在这些情况下,请运用 po,即表达式 — 目标描绘的别号。此版别还编译代码以评价表达式,但它会打印成果的目标描绘,您能够为您的目标自定义该描绘。

注意:

p 和po 的区别是,p或许只会打印目标的地址,然后po能够打印特点和其他详细的描绘。


(lldb) p self.testLabel
(LWZTestLabel *) $4 = 0x00000001074041a0
(lldb) po self.testLabel
<LWZTestLabel: 0x1074041a0; baseClass = UILabel; frame = (100 100; 100 50); text = '点击屏幕后的文字'; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x28354c190>>

(lldb) p self.tapNum
(NSInteger) $6 = 1
(lldb) po self.tapNum
1

经过增加调试描绘自定义调试器为您的目标显现的内容。在 Swift 中,为您的目标完成 CustomDebugStringProtocol。关于扩展 NSObject 的 Objective-C 目标,掩盖 debugDescription。

po 打印的输出的内容能够经过重写description办法更改,swift也有办法更改。

还能够经过po 或许p去更改内存变量的值。

当您打印运用协议声明的项目时, p 和 po 会打印过错,由于它们不履行迭代动态类型解析。当 p 或 po 打印过错时,运用 v 打印变量。


(lldb) po fruitItem.fruitName
error: <EXPR>:3:11: error: value of type 'FruitDisplayProtocol' has no member 'fruitName'
fruitItem.fruitName
~~~~~~~~~ ^~~~~~~~~
(lldb) v fruitItem.fruitName
(String) fruitItem.fruitName = "Apple

重点:


运用 Objective-C 时,lldb 不支持用于音讯发送的点表明法。运用括号表明法并将成果转换为 CGRect:
特别注意的是lldb不支持点的做法,只支持 [ ]的方式,这点很重要。