【iOS】bug调试技巧

【iOS】bug调试技巧

文章目录

前言

在写知乎日报这个项目的过程中我遇到了各式各样的一个bug,一个bug对于一个项目而言往往是非常致命的,我们有时候会因为一个小bug苦苦寻找20,30分钟,然后发现是一个简单的问题,所以笔者为此特地学习了有关于iOS开发中bug调试的内容。

断点(Breakpoint)

断点可以用来暂停程序运行,实时查看符号和对象。Xcode 支持多种不同类型的断点。例如:异常断点、符号断点等。下面就来介绍一些断点的使用场景。

Exception Breakpoint

我们在平常的项目中经常会出现下图的一个报错情况:

这里是一个数组越界的问题,但是却出现在了一个主函数中,很显然这种情况并不方便我们去定位我们的一个代码的问题,在一个项目中找到这种小问题,会非常麻烦,这里我们只需要三个步骤就可以让我们快速的找到报错的一个位置。

第一个步骤就是找到位于项目左侧的这个按钮:

然后找到项目左下角的一个添加按钮:

点击添加按钮后,点击Exception Breakpoint这个地方,然后我们就添加了一个断点,这个断点可以帮助我们快速的找到问题的所在。

下面看效果图:

可以看到我们的程序停在了数组越界的地方,这样是不是比之前自己主动去寻找数组越界的地方方便的多,然后这里一般情况是看不到控制台的一个打印信息的,

上面抛出异常时控制台是没有对应的错误信息输出的。下面介绍一个小技巧,在异常断点里面加一个 LLDB 命令:po $arg1。因为 objc_exception_throw 第一个参数就是异常信息本身,所以控制台就会打印出该异常对象。按照下图设置就可以了

这时候我们就可以在控制台看到报错的信息了

Symbolic Breakpoint

符号断点会在特定的某一个方法上打上断点,然后让程序停止在我们告知他的一个方法上。

设置的方法同样是和之前一样。

设置好符号断点后需要进行编辑,在 Symbol 填入符号,符号有以下几种:

  • 方法名 ,其会暂停所有该符号的调用。例如: removeFromSuperview,只要调用了removeFromSuperview 就会暂停程序执行
  • 类的一个方法 。例如: -[MyView1 removeFromSuperview]
  • C 函数 。例如: c_func

如图示方法添加即可:

​ 这里笔者其实还不是很清楚这个断点在什么场合中使用,这里笔者引用一段话:

符号断点可以在一些复杂业务和探索系统调用系统调用&zhida_source=entity)的场景下起到重要作用。例如有个 UIView 视图有多处对其进行了 removeFromSuperview 调用。如果你想了解其所有移除场景。那么你需要一个符号断点来协助你。这里有个注意的点就是在该类中必须有对应的方法实现。例如:-[MyView1 removeFromSuperview] 就需要在 MyView1 中重写 removeFromSuperview 方法,否则无法进入该符号断点。本人就利用过符号断点解决过一个 videoView 被误移除的 Bug。引用自:iOS-调试技巧

Constraint Error Breakpoint & Test Failure Breakpoint

笔者自己也没怎么使用过这两个断点,所以笔者直接引用一段话

这两种断点在实际开发当中使用的比较少。下面就简单介绍下其作用

  • Constraint Error Breakpoint:是一个自动布局约束错误断点,其可以帮你快速定位自动布局错误;
  • Test Failure Breakpoint:是一个单元测试UI测试失败断点,当测试失败时会直接暂时程序,其可以帮你快速定位测试失败原因。引用自:iOS-调试技巧

断点编辑

在很多情况中,我们往往不需要让某一个代码每次都停下,我们往往只需要一个条件下的一个某一个变量的情况,所以这时候断点编辑就有了他自己的一个意义,我们可以设置条件让这段代码在某些情况下停下,而且也可以自定义打印的一个信息,如下图所示,我们在一段代码的i == 2的情况下打上了断点

最后可以看到一个选项,这个选项的含义是可以让程序继续运行,这时候我们其实就可以有一个想法也就是我们是不是可以用断点来代替我们的NSLog的输出,他其实就可以实现这样的一个效果,笔者的控制台就会输出下文的内容:

这里来看笔者的一段实践操作,这里笔者给我们的y那一行代码打上了断点

然后给断点设置如下的一个打印信息的方式:

最后我们这里就实现了一个NSLog的一个效果,也就是我们这段代码里面没有任何的NSLog却可以把我们的一个Y全部打印出来:

设置观察点

观察点可以在某个变量中保存的值发生变化时暂停程序的执行。观察点可帮助解决与全局变量 / 单例对象有关的问题,追踪具体是哪个方法改变了特定的全局变量。此外,不能在程序未运行时添加观察点,必须在进入调试状态时在变量观察窗口进行观察点设置。设置方法如下图:

LLDB (Low Level Debugger)

LLDB 是 Xcode 内置动态调试工具。在程序进入断点时,Xcode 的调试控制台就会进入 LLDB 命令行调试状态。这里介绍一下一些简单的调试命令:

打印对象和标量

LLDB 最常用的命令就是 po (print object), 意为打印对象。po 可以打印当前作用域下的所有变量。例如:

复制代码
(lldb) po self

如果你需要打印一些标量(非对象)时,此时要用 p,而不是 po。例如:

bash 复制代码
(lldb) p (CGRect) self.view.bounds
(lldb) p (NSUInteger) self.myNumber

使用 po 还可以直接改变程序运行中的变量值。例如:self.myNumber = 10

bash 复制代码
(lldb) po self.myNumber = 10

Zombie Objects

  • Zombie Objects 一种用来检测内存错误(EXC_BAD_ACCESS)的对象,它可以捕获任何对尝试访问坏内存的调用。
  • 如果给 Zombie Objects 发送消息时,那么将在运行期间崩溃和输出错误日志。通过日志可以定位野指针对象调用的方法和类名。

开启方式:Product -> Scheme -> Edit Scheme -> Diagnostics -> Zombie Objects。

这些内容笔者还没用到,之后如果有用到再详细补充他的一个学习的内容。

Memory Graph

Memory Graph这个东西可以帮我们查找和修复被废弃的内存,它有点类似于 View Hierarchy,它可以很方便的查看对象的引用关系如果该对象存在一个内存泄漏,则该对象会被加上一个感叹好

我们可以看到如下图形:

小结

笔者简单介绍了一下iOS开发中调试的一个内容,这里也只是简单介绍了一下有哪些内容以及调试手段有什么,之后如何调试自己的项目其实主要还是看自己对于这些调试功能的熟练程度。笔者这篇文章也是初学调试的内容,如果有什么问题还请不吝指出。

参考博客:

相关推荐
黑化旺仔4 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
songgeb5 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙6 小时前
【iOS】swift启动屏显示黑屏
ios
用户69371750013847 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer7 小时前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户69371750013849 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
茶底世界之下9 小时前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco13511 小时前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记1 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_915921431 天前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview