前言
在开发过程中,调试是不可避免的,正常iOS的开发过程中,我们查看数据或者视图的位置大小,需要通过断点调试或者使用自带工具查看,这样就让我们的开发效率大大降低。如果延伸一下,我们还需要和UI部门、产品部门、Server部门、前端部门调试页面或者查询、校验数据等等,如果单纯的给出断点查看数据、工具查看视图信息,别人在等着着急,自己也不自在。所以为了解决这个痛点尝试做了一个小工具,把获取到的数据可视化,提高效率。
正常的调试过程:
构想
所需要可视化的对象
-
视图
目前iOS开发,绝大多数情况下是使用自定义视图以及自己封装的视图,一般在使用的时候会把他们设置为属性或者成员变量,来提高对视图本身和内容的操控性。
-
数据
关于数据的存储、传递、转换在项目中是十分重要的,为了数据持久化以及传递性提高,同视图一样,我们通常也会把他们设置为属性或者成员变量,重写set或者get方法方便赋值以及传递。常用Model、Array、Dictionary、JsonString等。
如何获取对象的内容
- Runtime
听到Runtime大家肯定很熟悉,我一个渣渣就不细说了,使用的方法也是最基本的,那就是:
①使用runtime方法获取属性列表
objc_property_t *properties = class_copyPropertyList([someclass class], &count);
②遍历对象通过KVC来取出对应属性的值
for (int i = 0; i < count; i++) {
// objc_property_t 属性类型
objc_property_t property = properties[i];
// 获取属性的名称 C语言字符串
const char * cName = property_getName(property);
// 转换为Objective C 字符串
NSString * name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
// 通过kvc来获取对饮属性的值
id propertyValue = [object valueForKey:(NSString*) name];
}
实践
所遇到的小问题
- 成员变量和属性
大家都知道runtime可以获取成员变量和属性,而且在获取成员变量的同时可以获得属性对象,也就是属性声明了一个someObject,在通过获取ivar的时候,会获得一个_someObject,头部带下划线的成员变量(属性)。所以在开发这个小工具的时候为了避免繁杂的过程和取值对比,最后采用的是:
Ivar * ivars = class_copyIvarList(className, &ivarCount);
通过这个方法来获得目标类的所有成员变量和属性。
-
区分好所需要的内容
做这个工具的初衷是为了让程序不被断点卡住的进行数据查看和核对,但是在开发过程中发现,咦,这个工具把所有的东西都扒出来了,视图、模型、数据存储类都可以查看,所以在工具里做了区分,以图片(金色圆点和银色圆点)为区分,金色圆点为普通数据,可以查看数组、字符串、View等等,银色圆点为Model,可以进入并查看Model内部更为详细的信息。 -
未能有效解决的痛点
传入[someObject class]的时候还需要传入someObject,前者用来获取ivar,后者用来通过KVC取值的时候作为取值的母体。
以下是核心代码
// 获取所需要的对象和对象的类
- (void)getProperties:(Class)className getObject:(id)object{
//初始化一个数据载体
NSMutableArray * array = [NSMutableArray array];
// 获取当前类的所有成员变量
unsigned int ivarCount;
Ivar * ivars = class_copyIvarList(className, &ivarCount);
for (int i = 0; i < ivarCount; i++) {
Ivar ivar = ivars[i];
const char * name = ivar_getName(ivar);
const char * type = ivar_getTypeEncoding(ivar);
// ivar所带出来的内容,有时候会为空,需要做判断
if (name != nil && type != nil) {
NSString *fieldsName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
NSString *fieldsStr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
// 通过kvc来获取成员变量的值
id fieldsValue = [object valueForKey:(NSString*)fieldsName];
NSString * appendStr = fieldsStr;
// 所获得的 fieldsStr 会包含 @ \ \ 等特殊字符,使用最基本的方式去除一下
appendStr = [appendStr stringByReplacingOccurrencesOfString:@"@"withString:@""];
appendStr = [appendStr stringByReplacingOccurrencesOfString:@"\""withString:@""];
appendStr = [appendStr stringByReplacingOccurrencesOfString:@"\""withString:@""];
// 这时候已经得到
/**
fieldsName 成员变量/属性 名称
appendStr 类型名称
fieldsValue 该变量所持有的值
*/
NSMutableDictionary * fieldsDic = [[NSMutableDictionary alloc]init];
[fieldsDic setValue:fieldsName forKey:@"name"];
[fieldsDic setValue:appendStr forKey:@"info"];
[fieldsDic setValue:fieldsValue forKey:@"value"];
[array addObject:fieldsDic];
}
}
// 初始化视图所需数据
dataArray = [NSMutableArray arrayWithArray:array];
// 展示视图
[self createUI];
}
效果
- 小工具流程图如下
- 使用方式和时机
推荐:可以在点击事件触发时候、可以在数据回调的时候、可以在页面消失的时候。
使用方式:
[[PropertyVisualiseTool sharedInstance]getProperties:[objc class] getObject: objc];
- 运行效果
结尾
代码已上传,放置链接在此https://download.csdn.net/download/werctzzz/10655897,客官们稍安勿躁。PS:不是我要收取资源分数啊,CSDN的分数最低设置是1,可能有人会问为什么不放到百度云,百度云如果下载人数多了或者分享次数多了会被屏蔽,谢谢理解。