未完待续,[继续总结]
LLDB && GDB
常用的Debug快捷键
功能 | 命令 |
---|---|
暂停/继续 | cmd + ctrl + Y |
断点失效/生效 | cmd + Y |
控制台显示/隐藏 | cmd + shift + Y |
光标切换到控制台 | cmd + shift + C |
清空控制台 | cmd + K |
step over | F6 |
step into | F7 |
step out | F8 |
技巧一:格式化输出数据
1、封装log函数
//swift版func DLog(message: T, file: String = #file, method: String = #function, line: Int = #line) { #if DEBUG print("<\((file as NSString).lastPathComponent) : \(line)>, \(method) \(message)") #endif}//OC版#ifdef DEBUG #define DLog(fmt, ...) NSLog((@"<%s : %d> %s " fmt), [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);#else #define DLog(...)#endif复制代码
2、代替NSLog,打印对象的内部属性
技巧二:条件断点(condition)
设置断点触发条件
注意:
// 正确(BOOL)[pId isEqualToString:@"short-videopage"]// 报错:error: no known method '-isEqualToString:'; cast the message send to the method's return type[pId isEqualToString:@"short-videopage"]复制代码
技巧三:运行中修改变量的值(expr & call)
在调试登录相关的bug时,非常方便,不用担心经常输密码,还输错的尴尬
调试UI,改变指定控件的颜色
技巧四:符号断点(Add Symbolic Breakpoint)
当我们查看一个陌生的项目的时候,我们可以先运行APP,对所有的
viewDidLoad
函数添加断点,进而了解代码执行路径Symbol
:符号
- c语言,
methodName
只需要写函数名,不用写后面的() - oc样式,
[className methodName]
className是类名,methodName是方法名(不区分类方法和实例方法) - swift样式,
ClassName.methodName
Module
模块筛选:可以避免不同库中方法名或者函数名相同 Condition
触发条件
这里可以添加一些指定触发条件,比如添加第一个参数(arg3)不能为nil。这里arg4代表第2个参数,以此类推。这里也可以调用方法来判断,但必须是类方法,并且返回值必须为BOOL类型。 样例:找出给[UIImage imageNamed:]传nil的代码。这里就需要设置Symbol为
查看某一个函数需要添加断点的符号填写格式(在需要调试的函数打上断点,程序运行走到断点后,从堆栈信息中查看相应函数的格式)[UIImage imageNamed:]
,然后Condition设置为$arg3 == nil
。这样在运行中如果遇到传nil就会触发断点。
技巧五:全局异常断点(Add Exception Breakpoint)
技巧六:查看整体UI层级结构(debug view hierarchy)
如果电脑配置较低,最好使用
chisel
插件命令pviews
技巧七:开启僵尸模式(EXC_BAD_ACCESS)
遇到EXC_BAD_ACCESS这个错误,那就意味着你向一个已经释放的对象发送消息。Xcode知道这个对象是什么,所以可以让我们知道这个对象在哪里,以及这是什么时候发生的。当开启僵尸模式后,遇到EXC_BAD_ACCESS,xcode可以帮我们快速定位到出现问题的代码。
开启僵尸模式:
技巧八:查看frame的值
导入@import UIKit
(lldb) p self.view.frameerror: property 'frame' not found on object of type 'UIView *'error: 1 errors parsing expression(lldb) e @import UIKit(lldb) p self.view.frame(CGRect) $0 = (origin = (x = 0, y = 0), size = (width = 375, height = 667))复制代码
或者(CGRect)
print (CGRect)[view frame](CGRect) $1 = (origin = (x = 0, y = 0), size = (width = 200, height = 100))复制代码
技巧九:监听所有的点击事件(UIControl、Touch、Gesture)
方法:覆写UIAppliaction
.h文件
#importNS_ASSUME_NONNULL_BEGIN@interface CustomApplication : UIApplication@endNS_ASSUME_NONNULL_END复制代码
.m文件
#import "CustomApplication.h"@implementation CustomApplication-(void)sendEvent:(UIEvent *)event { [super sendEvent:event];}@end复制代码
main.m文件
#import#import "AppDelegate.h"#import "CustomApplication.h"int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, NSStringFromClass([CustomApplication class]), NSStringFromClass([AppDelegate class])); }}复制代码
方法执行
一次事件可能会执行三次函数:
-(void)sendEvent:(UIEvent *)event
三次的force
有区别
一次事件可能会执行两次函数:
-(void)sendEvent:(UIEvent *)event
两次的force
没区别
响应者链条
1、如果是
UIControl
事件,集成UIResponder
控件(UIButton
)消息传递链(倒序)如下图所示
2、如果是
UIGestureRecognizer
手势事件,集成UIResponder
控件(UIView
)消息传递链(倒序)如下图所示
3、如果
UIControl
和UIGestureRecognizer
同时存在,优先级高
其他工具:1、
Chisel是faceBook开源的lldb调试命令集合
安装()
Chisel 使用 来安装
brew updatebrew install chisel复制代码
安装完成后,将下面的命令添加到~/.lldbinit
中,xcode启动的时候才会加载chisel
command script import /usr/local/opt/chisel/libexec/fblldb.py复制代码
常用命令
查看帮助(lldb) help复制代码
参考:
其他工具:2、
Reveal 绝对是iOS界面调试利器。使用起来不仅比Xcode自带流畅,而且功能更加多。由于收费,30天过后就没怎么用但是绝对好用。
大约有4中集成方法,详情参加 。其他工具:3、
FLEX是Flipboard开源的一系列在应用中调试的工具集。FLEX以第三方库的形式集成在应用中,使用时将类库加到工程中,然后 通过调用[[FLEXManager sharedManager] showExplorer]; 就可显示出用于调试的工具栏进行调试。
它提供的功能如下:
- 查看、修改views
- 查看任何对象的属性
- 动态的修改属性
- 动态的调用实例方法和类方法
- 查看网络请求过程
- 添加模拟的键盘快捷键
- 查看系统日志
- 从堆中获取任何对象
- 查看沙盒中的文件
- 查看文件系统中的SQLite/Realm数据库
- 在模拟器中触发3D touch
- 查看你应用中所有的类
- 快速获取常用的类,例如[UIApplication sharedApplication], the app delegate, the root view controller on the key window, and more.
- 动态的查看NSUserDefaults里面的值