Post

YourView源码研究与学习

YourView源码研究与学习

YourView 研究

项目地址

https://github.com/TalkingData/YourView

由于项目比较老,运行起来时有个地方会报错,需要修改如下,在_snapWithSublayer的最前面增加判断width或height是否为0,为0的直接返回为空,否则会崩溃

1
2
3
4
5
6
7
8
9
# UIView+YVNodeInfo.m
-(NSString*)_snapWithSublayer:(BOOL)containSublayer
{
    CGRect frameX = self.frame;
    if (frameX.size.width <= 0 || frameX.size.height <= 0) {
        return @"";
    }
....
}

代码调用流程

1、启动Web服务器

1、利用项目启动时,所有类都会执行load方法, ,启动GCDWebServer服务器: TalkingDataSDKDemo/libyourview/main/Main.m-> +(void)load -> +(void)_main -> GCDWebServer
GET: -> Main._excuteCmd

2、请求App信息

GET url http://127.0.0.1:8080/?cmd=appinfo -> Main._excuteCmd -> 返回App相关信息

3、获取最新的view及相关信息

GET url: http://127.0.0.1:8080/?cmd=viewtree -> Main._excuteCmd -> 同步主流程 rootViewTreeDictionary -> 递归查下view及子节点view的信息 [keyWindow traversal:stepIn context:context] -> nodeInfo -> 每个view的信息 frame相对于window的frame_snapWithSublayer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// "YVTraversalStepin.h"
// 层级信息
(lldb) po [stepined stepinfo]
{
    "assign_to_viewcontroller" = "";
    "index_row" = "-1";
    "index_section" = "-1";
    "is_in_collectionview" = 0;
    "is_in_tableview" = 0;
    "view_deepth" = 0;
    "view_level" = "/0";
}
// "NSObject+YVNodeInfo.h"
// 类,地址、继承关系
po superinfo
{
    address = 0x10361cfc0; // [NSString stringWithFormat:@"%p",self]
    class = UIWindow; // NSStringFromClass(self.class)
    inherit = "UIWindow:UIView:UIResponder:NSObject"; // 不断递归找到superClass
}
// "UIView+YVNodeInfo.h"
// layer的截图的base64、frame
 po selfinfo
{
    isoffscreen = 0;
    localframe = "{0, 0, 393, 852}";
    snapshot = "iVBORw0KGgoAA...";
    windowframe = "{0, 0, 393, 852}";
}
// "UIView+YVTraversal.h"
// 记录每个view及subview的address,以及记录总view数量
po extraInfo
{
    screeninfo = "{0, 0, 393, 852}";
    totalcount = 55;
}
// respons 返回的内容:
{
    "viewtree": stepinfo + nodeInfo=(superInfo+selfInfo),
    "extraInfo": extraInfo
}
 + 
4、点击Here,摇动选择的view

GET url: http://127.0.0.1:8080/?cmd=shake&address=0x1036181b0 -> Main._excuteCmd -> 根据address找到缓存的view[[YVObjectManager sharedInstance].context.viewMap objectForKey:addresss] -> shake2 -> 执行layer的transform.translation.x 动画

5、跟新选中view的frame

POST url: http://127.0.0.1:8080/?cmd=setframe&address=0x10368b9f0-> 根据address找到缓存的view[[YVObjectManager sharedInstance].context.viewMap objectForKey:addresss] -> setFrame -> 执行


Mac端软件展示逻辑

1、填写ip并点击按钮

buttonPressed -> "http://%@:8080?cmd=appinfo" -> onAppInfoSuccess -> requestViewTree -> http://"http://%@:8080?cmd=viewtree" -> [windowController updateViewTree:dict] -> notifyDataSuccess -> 通知YVViewTreeDidLoadNotificationName

2、点击刷新按钮

onRefreshButtonEvent -> "http://%@:8080?cmd=viewtree" -> notifyDataSuccess -> 通知YVViewTreeDidLoadNotificationName

左侧树形结构 YVLeftViewController -> YVViewTreeDidLoadNotificationName -> dataOK -> viewTree -> dataSource -> reloadData -> NSOutlineView

中间UI展示 YVMiddleViewController -> YVViewTreeDidLoadNotificationName -> dataOK -> viewTree -> dataSource -> createView -> NSNode + snapshot

image image image image

This post is licensed under CC BY 4.0 by the author.