├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── VZInspector.podspec
├── VZInspector
├── VZDefine.h
├── VZInspector.h
├── VZInspector.m
├── core
│ ├── NSObject+VZInspector.h
│ ├── NSObject+VZInspector.m
│ ├── VZInspectController.h
│ ├── VZInspectController.m
│ ├── VZInspectorAssert.h
│ ├── VZInspectorOverlay.h
│ ├── VZInspectorOverlay.m
│ ├── VZInspectorResource.h
│ ├── VZInspectorResource.m
│ ├── VZInspectorTimer.h
│ ├── VZInspectorTimer.m
│ ├── VZInspectorUtility.h
│ ├── VZInspectorUtility.m
│ ├── VZInspectorView.h
│ ├── VZInspectorView.m
│ ├── VZInspectorWindow.h
│ ├── VZInspectorWindow.m
│ ├── item
│ │ ├── VZInspectorBizLogItem.h
│ │ └── VZInspectorBizLogItem.m
│ ├── keycommand
│ │ ├── VZKeyCommands.h
│ │ └── VZKeyCommands.m
│ ├── manager
│ │ ├── VZInspectorBizLogManager.h
│ │ └── VZInspectorBizLogManager.m
│ └── view
│ │ ├── VZInspectorBizLogCell.h
│ │ ├── VZInspectorBizLogCell.m
│ │ ├── VZInspectorBizLogToolBarItem.h
│ │ ├── VZInspectorBizLogToolBarItem.m
│ │ ├── VZInspectorBizLogView.h
│ │ ├── VZInspectorBizLogView.m
│ │ ├── VZInspectorMaskView.h
│ │ ├── VZInspectorMaskView.m
│ │ ├── VZInspectorSearchBar.h
│ │ ├── VZInspectorSearchBar.m
│ │ ├── VZInspectorTagListView.h
│ │ ├── VZInspectorTagListView.m
│ │ ├── VZInspectorTagView.h
│ │ └── VZInspectorTagView.m
├── log
│ ├── VZInspectorLogView.h
│ ├── VZInspectorLogView.m
│ ├── VZLogInspector.h
│ └── VZLogInspector.m
├── overview
│ ├── VZInspectorOverview.h
│ ├── VZInspectorOverview.m
│ ├── VZInspectorPlotView.h
│ ├── VZInspectorPlotView.m
│ ├── VZOverviewInspector.h
│ ├── VZOverviewInspector.m
│ ├── controller
│ │ ├── VZControllerStack.h
│ │ └── VZControllerStack.m
│ ├── device
│ │ ├── VZDevice.h
│ │ └── VZDevice.m
│ ├── env
│ │ ├── VZInspectorSettingView.h
│ │ ├── VZInspectorSettingView.m
│ │ ├── VZSettingInspector.h
│ │ └── VZSettingInspector.m
│ └── memory
│ │ ├── VZMemoryInspector.h
│ │ ├── VZMemoryInspector.m
│ │ ├── VZMemoryInspectorOverView.h
│ │ └── VZMemoryInspectorOverView.m
└── toolbox
│ ├── VZInspectorToolItem.h
│ ├── VZInspectorToolItem.m
│ ├── VZInspectorToolboxView.h
│ ├── VZInspectorToolboxView.m
│ ├── border
│ ├── VZBorderInspector.h
│ └── VZBorderInspector.m
│ ├── colorPicker
│ ├── VZColorDisplayView.h
│ ├── VZColorDisplayView.m
│ ├── VZColorPanelView.h
│ ├── VZColorPanelView.m
│ ├── VZColorPickerDefine.h
│ ├── VZInspectorColorPickerView.h
│ └── VZInspectorColorPickerView.m
│ ├── crash
│ ├── VZCrashInspector.h
│ ├── VZCrashInspector.m
│ ├── VZInspectorCrashRootView.h
│ ├── VZInspectorCrashRootView.m
│ ├── VZInspectorCrashView.h
│ └── VZInspectorCrashView.m
│ ├── framerate
│ ├── VZFrameRateOverlay.h
│ └── VZFrameRateOverlay.m
│ ├── grid
│ ├── UIWindow+VZInspector.h
│ ├── UIWindow+VZInspector.m
│ ├── VZInspectorGridView.h
│ └── VZInspectorGridView.m
│ ├── image
│ ├── VZInspectorImageInfoView.h
│ └── VZInspectorImageInfoView.m
│ ├── location
│ ├── CLLocationManager+FLFake.h
│ ├── CLLocationManager+FLFake.m
│ ├── FLFakeConfig.h
│ ├── FLFakeConfig.m
│ ├── VZInspectorLocationView.h
│ └── VZInspectorLocationView.m
│ ├── network
│ ├── VZInspectorNetworkDetailView.h
│ ├── VZInspectorNetworkDetailView.m
│ ├── VZInspectorNetworkHistoryView.h
│ ├── VZInspectorNetworkHistoryView.m
│ ├── VZNetworkInspector.h
│ ├── VZNetworkInspector.m
│ ├── VZNetworkInspectorOverView.h
│ ├── VZNetworkInspectorOverView.m
│ ├── VZNetworkObserver.h
│ ├── VZNetworkObserver.m
│ ├── VZNetworkRecorder.h
│ ├── VZNetworkRecorder.m
│ ├── VZNetworkTransaction.h
│ └── VZNetworkTransaction.m
│ └── sandbox
│ ├── VZInspectorSandBoxRootView.h
│ ├── VZInspectorSandBoxRootView.m
│ ├── VZInspectorSandBoxSubView.h
│ └── VZInspectorSandBoxSubView.m
├── VZInspectorDemo.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ └── VZInspectorDemo.xcscheme
├── VZInspectorDemo
├── AppDelegate.h
├── AppDelegate.m
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
├── ViewController.h
├── ViewController.mm
└── main.m
└── logo.png
/.gitignore:
--------------------------------------------------------------------------------
1 | wp
2 | # Xcode
3 | #
4 | build/
5 | *.pbxuser
6 | !default.pbxuser
7 | *.mode1v3
8 | !default.mode1v3
9 | *.mode2v3
10 | !default.mode2v3
11 | *.perspectivev3
12 | !default.perspectivev3
13 | xcuserdata
14 | *.xccheckout
15 | *.moved-aside
16 | DerivedData
17 | *.hmap
18 | *.ipa
19 | *.xcuserstate
20 | xcuserdata/
21 | *.xccheckout
22 | contents.xcworkspacedata
23 |
24 | # CocoaPods
25 | #
26 | # We recommend against adding the Pods directory to your .gitignore. However
27 | # you should judge for yourself, the pros and cons are mentioned at:
28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29 | #
30 | Pods/*
31 | Pods
32 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode8.3
3 | branches:
4 | only:
5 | - master
6 | script: xcodebuild -project VZInspectorDemo.xcodeproj -scheme VZInspectorDemo -sdk iphonesimulator
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2013-2017 VZInspector (jayson.xu@foxmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | # VZInspector
5 |
6 | [](http://cocoapods.org/pods/VZInspector)
7 | [](http://cocoapods.org/pods/VZInspector)
8 | [](http://cocoapods.org/pods/VZInspector)
9 | [](http://cocoapods.org/pods/VZInspector)
10 |
11 | > This project is no longer being actively developed or maintained.
12 |
13 |
14 | ## 简介
15 |
16 | VZInspector 是一个给 iOS 开发者使用的 debug 工具,包含日志查询、取色、控件检查、视觉稿比对等功能,同时提供了丰富的接口方便自行定制。
17 |
18 | ## 接入
19 |
20 | ### 使用 Cocoapods
21 |
22 | ```
23 | pod 'VZInspector'
24 | ```
25 |
26 | Pod安装成功后,在`AppDelegate.m`中引入头文件:
27 |
28 | ```objc
29 | #import "VZInspector/VZInspector.h"
30 | ```
31 |
32 | 在`AppDelegate.m`中配置`VZInspector`插件
33 |
34 | ```objc
35 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
36 |
37 | //some code above...
38 |
39 | [VZInspector setClassPrefixName:@"VZ"];
40 | [VZInspector setShouldHandleCrash:true];
41 | [VZInspector setShouldHookNetworkRequest:true];
42 | [VZInspector setLogNumbers:10];
43 | [VZInspector showOnStatusBar];
44 |
45 | //some code below
46 | }
47 | ```
48 |
49 | ## 功能说明
50 |
51 | 这部分按照 VZInspector 界面上的功能区块,分别介绍 VZInspector 内置的功能以及可自定义的功能。
52 |
53 | 
54 |
55 | ### 内存占用
56 |
57 | App 当前内存占用显示在 Status 顶部,折线显示内存占用变化趋势。
58 |
59 |
60 |
61 | ### Dashboard
62 |
63 | 这里显示一些常用信息,比如 uid、视图栈、特定 UserDefaults 的值等,默认显示设备信息和视图栈,可以通过以下代码自定义该区域内容。点击“R”按钮会重新获取该区域内容。
64 |
65 | ```c
66 | + (void)setupVZInspector {
67 | [VZInspector addObserveCallback:^NSString *{
68 | //返回需要追加显示的信息
69 | }];
70 | }
71 |
72 | ```
73 |
74 |
75 |
76 | ### 自定义
77 |
78 | 在 Memory Usage 区域上面有一个自定义区域,供你放置一些开关,例如我们在这里做了环境切换、清理内存缓存的功能,环境切换功能深受测试同学喜欢。自定义示例如下:
79 |
80 |
81 |
82 | ```c
83 | //自定义 Dashboard 开关
84 | [VZInspector addDashboardSwitch:@"发布环境" Highlight:productEnv?:NO Callback:^{
85 | //按钮点击动作
86 | }];
87 | ```
88 |
89 | ## Log
90 |
91 | Log 界面显示 NSLog 输出的信息,可以在不连接 Xcode 时直接查看日志,最新的日志在顶部显示。此外顶部提供了过滤功能;右下区域的三个按钮分别对应 `回到顶部`、`打开/关闭自动刷新` 和 `刷新` 操作。
92 |
93 |
94 |
95 | ### 自定义
96 |
97 | 顶部搜索框可以进行简单过滤,为了避免每次输入相同关键词,你可以用下面的代码添加关键词过滤按钮。
98 |
99 | ```c
100 | //设置 Log 过滤关键词
101 | [VZLogInspector sharedInstance].searchList = @[@"keyword1", @"keyword2"];
102 | ```
103 |
104 | 设置好的关键词会以按钮形式显示,点击即可显示相应关键词的过滤结果。
105 |
106 |
107 |
108 | ## Toolbox
109 |
110 | Toolbox 界面提供了一些常用小工具,例如网络日志查看、控件检查、帧率监测。开关类的工具在打开时会在右上角显示 `ON`。
111 |
112 |
113 |
114 | ### Logs
115 |
116 | Logs 用来实时查看网络请求的状态、返回等,需要自行配置网关信息,如下所示:
117 |
118 | ```c
119 | + (void)setupNetworkMonitorConfig
120 | {
121 | [VZInspector setShouldHookNetworkRequest:true];
122 |
123 | [[VZNetworkInspector sharedInstance] addTransactionTitleFilter:^NSString *(VZNetworkTransaction *transaction) {
124 | if ([transaction.request.URL.host rangeOfString:@"YourGatewayKeyword"].location != NSNotFound) {
125 | NSString *operationType = [transaction.request valueForHTTPHeaderField:@"Operation-Type"];
126 | if (operationType.length == 0) {
127 | NSData *bodyData = [transaction postBodyData];
128 | NSString *body = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
129 |
130 | NSString *parten = @"operationType=([a-zA-Z0-9.]*)";
131 | NSRegularExpression *reg = [NSRegularExpression regularExpressionWithPattern:parten options:kNilOptions error:nil];
132 | NSTextCheckingResult* match = [reg firstMatchInString:body options:kNilOptions range:NSMakeRange(0, [body length])];
133 | if (match) {
134 | operationType = [body substringWithRange:[match rangeAtIndex:1]];
135 | }
136 | }
137 | if (operationType.length > 0) {
138 | return operationType;
139 | }
140 | }
141 | return nil;
142 | }];
143 |
144 | [VZNetworkInspector setIgnoreDelegateClasses:[NSSet setWithObjects:@"ClassesYouWantToIgnore", nil]];
145 | }
146 | ```
147 |
148 |
149 |
150 | ### Crash
151 |
152 | 可以捕获 App 的 Crash 日志,开启方法:
153 |
154 | ```c
155 | //打开 crash 捕获
156 | [VZInspector setShouldHandleCrash:YES];
157 | ```
158 |
159 |
160 |
161 | ### Sandbox
162 |
163 | 用来展示应用沙盒文件,对于文本和图片文件,点击可以预览。
164 |
165 | ### Grid
166 |
167 | 网格工具用来做视觉检查,比如简单的控件对齐、控件尺寸等。
168 |
169 |
170 |
171 | #### Border
172 |
173 | 边框检查工具能显示当前界面所有控件的边框,可以用来进行视觉检查。此外你可以设置类前缀关键词,比如“O2O”,这样就会将所有“O2O”开头的类的类名显示出来。
174 |
175 | ```c
176 | //自定义显示类名的控件类前缀
177 | [VZInspector setClassPrefixName:@"O2O"];
178 | ```
179 |
180 |
181 |
182 | ### Warning
183 |
184 | Warning 用来模拟内存警告,可以帮你验证 `didReceiveMemoryWarning` 里的逻辑,当打开的时候,可以在 “Memory Usage” 区域看到红色闪烁标识。
185 |
186 |
187 |
188 | ### Image
189 |
190 | Image 工具用于检查界面上的图片,比如查看图片尺寸,图片 URL。
191 |
192 |
193 |
194 | 工具栏的按钮从左到右依次为:
195 | - **返回**
196 | - **分享**,可以在手机上把当前选择的图片 AirDrop 到电脑上
197 | - **复制**,可以把选择的图片和描述复制到剪切板,再按 Ctrl+C 从模拟器复制出来
198 | - **切换**,点击切换是否开启选择模式,关闭选择模式来操作界面
199 |
200 | 选择图片后会把图片置顶显示,并显示出被裁剪的部分。
201 | 屏幕上方(或下方)显示图片和 View 的尺寸、scale、宽高比,图片帧数。另外 O2O 中额外增加了图片 URL 的显示。
202 |
203 |
204 |
205 | 如果点击的位置有多个重叠的图片,可以多次点击来切换选择的图片。
206 |
207 | ### Location
208 |
209 | Location 工具用来模拟经纬度,打开开关后输入经纬度即可。界面上也提供了一些常用城市的经纬度。
210 |
211 |
212 |
213 | ### FrameRate
214 |
215 | 帧率监测工具可以将帧率显示在状态栏上。注:模拟器无法精准检测帧率,仅在真机上有效。
216 |
217 |
218 |
219 | ### ColorPicker
220 |
221 | 提供屏幕取色的功能。
222 | - 按像素取值,并将颜色展示在下面控制板
223 | - 拖动底部的slider可以控制放大倍率(5 ~ 30倍)
224 | - 拖动取色器可以移动取色的位置,在取色器外滑动可以慢速移动,方便按像素取值移动
225 |
226 |
227 |
228 |
229 |
230 | ## Plugin
231 |
232 | 插件界面方便你在 VZInspector 中放置自己开发的插件,如下图所示。这部分完全是业务相关的工具,可以使用下面的代码进行自定义。
233 |
234 |
235 |
236 | ```c
237 | //添加自定义插件
238 | VZInspectorToolItem *scan = [VZInspectorToolItem itemWithName:@"scan" icon:icon callback:^{
239 | //按钮点击动作
240 | }];
241 | [VZInspector addToolItem:scan];
242 | ```
243 |
244 | # License
245 |
246 | VZInspector 基于 MIT License,更多信息查看:https://opensource.org/licenses/MIT
247 |
248 | # Contribution
249 |
250 | 欢迎任何建议 & Pull request。
251 |
--------------------------------------------------------------------------------
/VZInspector.podspec:
--------------------------------------------------------------------------------
1 |
2 |
3 | Pod::Spec.new do |s|
4 |
5 | s.name = "VZInspector"
6 | s.version = "0.1.8"
7 | s.summary = "an iOS app runtime debugger"
8 | s.homepage = "https://github.com/xta0/VZInspector"
9 | s.license = "MIT"
10 | s.author = { "xta0" => "xta0.me@gmail.com" }
11 | s.platform = :ios, "8.0"
12 | s.ios.deployment_target = "8.0"
13 | s.source = { :git => "https://github.com/xta0/VZInspector", :tag => "#{s.version}" }
14 | s.requires_arc = true
15 | s.framework = 'Foundation', 'UIKit', 'CoreGraphics', 'QuartzCore'
16 | s.source_files = 'VZInspector/**/*.{h,c,m,mm}'
17 | s.libraries = "z", "c++"
18 | s.xcconfig = {
19 | 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11',
20 | 'CLANG_CXX_LIBRARY' => 'libc++'
21 | }
22 | end
23 |
--------------------------------------------------------------------------------
/VZInspector/VZDefine.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | #define fequal(a,b) (fabs((a) - (b)) < FLT_EPSILON)
8 | #define fequalzero(a) (fabs(a) < FLT_EPSILON)
9 | #define flessthan(a,b) (fabs(a) < fabs(b)+FLT_EPSILON)
10 |
11 | /**
12 | * 用一个24位的整数生成UIColor
13 | * 这个方法实现如下,只会返回不透明的颜色
14 | return [UIColor colorWithRed:((rgb & 0xFF0000) >> 16) / 255.0f
15 | green:((rgb & 0xFF00) >> 8) / 255.0f
16 | blue:((rgb & 0xFF)) / 255.0f
17 | alpha:1.0f];
18 | * @param rgb 形如0xRRGGBB
19 | */
20 | #define VZ_RGBA( rgb , a) [UIColor colorWithRed:((rgb & 0xFF0000) >> 16 ) / 255.0f green:((rgb & 0xFF00) >> 8)/255.0f blue:((rgb & 0xFF)) / 255.0f alpha:a ]
21 | #define VZ_RGB(rgb) VZ_RGBA(rgb ,1.0f )
22 |
23 | #define VZ_INSPECTOR_MAIN_COLOR VZ_RGB(0xfd8023)
24 |
25 |
26 | #define screen_width [UIScreen mainScreen].bounds.size.width
27 |
28 | #define VZ_TextSizeFrame(text , fontSize) [text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:fontSize]} context:nil].size
29 |
30 | #define vz_IsStringValid(_str) (_str && [_str isKindOfClass:[NSString class]] && ([_str length] > 0))
31 | #define vz_IsArrayValid(_array) (_array && [_array isKindOfClass:[NSArray class]] && ([_array count] > 0))
32 | #define vz_IsDictionaryValid(__dic) (__dic && [__dic isKindOfClass:[NSDictionary class]] && ([__dic count] > 0))
33 |
34 | #define kOnePix (1.0f/[UIScreen mainScreen].scale)
35 |
36 |
--------------------------------------------------------------------------------
/VZInspector/VZInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZInspectController.h"
7 | #import "VZInspectorToolItem.h"
8 |
9 | @interface VZInspector : NSObject
10 |
11 | /*
12 | *在状态栏显示入口
13 | */
14 | + (void)showOnStatusBar;
15 | + (BOOL)isShow;
16 | /*
17 | *打开inspector
18 | */
19 | + (void)show;
20 | /*
21 | *关闭inspector
22 | */
23 | + (void)hide;
24 | /*
25 | *设置业务类代码前缀
26 | */
27 | + (void)setClassPrefixName:(NSString* )name;
28 | /*
29 | *是否要记录crash日志
30 | */
31 | + (void)setShouldHandleCrash:(BOOL)b;
32 | /**
33 | *是否要hook网络请求
34 | */
35 | + (void)setShouldHookNetworkRequest:(BOOL)b;
36 | /**
37 | * 设置log数量限制
38 | */
39 | + (void)setLogNumbers:(NSUInteger)num;
40 | /*
41 | *注入要观察的全局信息
42 | */
43 | + (void)addObserveCallback:(NSString* (^)(void)) callback;
44 | /**
45 | * 注入自定义插件
46 | */
47 | + (void)addToolItem:(VZInspectorToolItem *)toolItem;
48 | /*
49 | * 返回所有注册的自定义插件
50 | */
51 | + (NSArray *)additionTools;
52 |
53 | @end
54 |
55 |
56 | @interface VZInspector(env)
57 | /**
58 | * 增加 Dashboard 头部开关
59 | */
60 | + (void)addDashboardSwitch:(NSString* )type Highlight:(BOOL)highligh Callback:(void(^)(void))callback;
61 |
62 |
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/VZInspector/VZInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspector.h"
6 | #import "VZInspectorOverlay.h"
7 | #import "VZInspectorWindow.h"
8 | #import "VZCrashInspector.h"
9 | #import "VZOverviewInspector.h"
10 | #import "VZSettingInspector.h"
11 | #import "VZLogInspector.h"
12 | #import "VZNetworkObserver.h"
13 | #import "VZBorderInspector.h"
14 | #import "VZInspectorToolboxView.h"
15 | #import "VZDevice.h"
16 |
17 |
18 | @implementation VZInspector
19 |
20 |
21 |
22 | + (void)showOnStatusBar
23 | {
24 | //dispatch to the next runloop
25 | dispatch_async(dispatch_get_main_queue(), ^{
26 | [VZInspectorOverlay show];
27 | });
28 |
29 | }
30 |
31 | + (BOOL)isShow
32 | {
33 | return ![VZInspectorWindow sharedInstance].hidden;
34 | }
35 |
36 | + (void)show
37 | {
38 | // NSData *data = [NSData dataWithContentsOfFile:@"/Users/lingwan/ios-phone-o2o-debug/VZInspector/aa.png"];
39 | // NSUInteger len = [data length];
40 | // Byte *byteData = (Byte*)malloc(len);
41 | // memcpy(byteData, [data bytes], len);
42 | //
43 | // for (int i=0; i
6 |
7 | @interface NSObject (VZInspector)
8 |
9 | /**
10 | for debugger use
11 | */
12 | @property(nonatomic,strong) NSMutableArray* samplePoints;
13 | /**
14 | for debugger use
15 | */
16 | - (void)vz_heartBeat;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/VZInspector/core/NSObject+VZInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "NSObject+VZInspector.h"
6 | #include
7 |
8 |
9 | @implementation NSObject (VZInspector)
10 |
11 | - (void)setSamplePoints:(NSMutableArray *)samplePoints
12 | {
13 | objc_setAssociatedObject(self, "samplePoints", samplePoints, OBJC_ASSOCIATION_RETAIN);
14 | }
15 |
16 | - (NSString*)samplePoints
17 | {
18 | return objc_getAssociatedObject(self, "samplePoints");
19 | }
20 |
21 | - (void)vz_heartBeat
22 | {
23 |
24 | }
25 |
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectController.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @class VZInspectorToolboxView;
8 |
9 | @interface VZInspectController : UIViewController
10 |
11 | @property(nonatomic,strong,readonly) UIView* currentView;
12 | @property(nonatomic,assign,readonly) NSString* currentTab;
13 |
14 | @property(nonatomic,strong) VZInspectorToolboxView* toolboxView;
15 | @property(nonatomic,strong) VZInspectorToolboxView* pluginView;
16 |
17 | - (void)start;
18 | - (void)stop;
19 | - (BOOL)canTouchPassThrough:(CGPoint)pt;
20 | - (void)onClose;
21 | - (void)transitionToView:(UIView *)view;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorAssert.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #ifndef VZInspector_VZInspectorAssert_h
6 | #define VZInspector_VZInspectorAssert_h
7 |
8 | #include
9 |
10 |
11 |
12 | static inline BOOL vz_isMainThread(){return 0 != pthread_main_np();};
13 | #define VZIPAssert(...) Assert(__VA_ARGS__)
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorOverlay.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorOverlay : UIWindow
8 |
9 | +(instancetype)sharedInstance;
10 | +(void)show;
11 | +(void)hide;
12 |
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorOverlay.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorOverlay.h"
6 | #import "VZInspector.h"
7 | #import "VZInspectorResource.h"
8 |
9 |
10 | @implementation VZInspectorOverlay
11 |
12 | + (instancetype)sharedInstance
13 | {
14 | static VZInspectorOverlay* instance = nil;
15 | static dispatch_once_t onceToken;
16 | dispatch_once(&onceToken, ^{
17 |
18 | int x = [UIScreen mainScreen].bounds.size.width > 320 ? 250 :180 ;
19 | instance = [[VZInspectorOverlay alloc]initWithFrame:CGRectMake(x, 0, 60, 20)];
20 | });
21 | return instance;
22 |
23 | }
24 |
25 | +(void)show
26 | {
27 | VZInspectorOverlay* o = [self sharedInstance];
28 | o.tag = 100;
29 | o.windowLevel = UIWindowLevelStatusBar+1;
30 | o.hidden = NO;
31 | }
32 | +(void)hide
33 | {
34 | for (UIWindow* window in [UIApplication sharedApplication].windows) {
35 | if ([window isKindOfClass:[VZInspectorOverlay class]]) {
36 | window.hidden = YES;
37 | break;
38 | }
39 | }
40 | }
41 | - (id)initWithFrame:(CGRect)frame
42 | {
43 | self = [super initWithFrame:frame];
44 |
45 | if ( self )
46 | {
47 | self.backgroundColor = [UIColor clearColor];
48 |
49 | UIImageView* imgv = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
50 | imgv.contentMode = UIViewContentModeScaleAspectFit;
51 | imgv.image = [VZInspectorResource eye];
52 | imgv.userInteractionEnabled = true;
53 | [imgv addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onSelfClicked:)]];
54 | [self addSubview:imgv];
55 |
56 | }
57 | return self;
58 | }
59 |
60 | - (void)onSelfClicked:(UIButton* )sender
61 | {
62 | if([VZInspector isShow])
63 | [VZInspector hide];
64 | else
65 | [VZInspector show];
66 | }
67 |
68 | - (void)becomeKeyWindow
69 | {
70 | //fix keywindow problem:
71 | //UIActionSheet在close后回重置keywindow,防止自己被设成keywindow
72 | [[[UIApplication sharedApplication].delegate window] makeKeyWindow];
73 | }
74 |
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorResource.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import
7 |
8 | #define VZ_IMAGE(BYTE_ARRAY) [VZInspectorResource imageWithBytes:BYTE_ARRAY length:sizeof(BYTE_ARRAY)]
9 | #define VZ_IMAGE_SCALE(BYTE_ARRAY, SCALE) [VZInspectorResource imageWithBytes:BYTE_ARRAY length:sizeof(BYTE_ARRAY) scale:SCALE]
10 |
11 | @interface VZInspectorResource : NSObject
12 |
13 | + (UIImage *)imageWithBytes:(const uint8_t *)bytes length:(size_t)length;
14 | + (UIImage *)imageWithBytes:(const uint8_t *)bytes length:(size_t)length scale:(CGFloat)scale;
15 |
16 | + (UIImage *)logo;
17 |
18 | + (UIImage *)eye;
19 |
20 | + (UIImage *)grid;
21 |
22 | + (UIImage *)sandbox;
23 |
24 | + (UIImage *)network_logs;
25 |
26 | + (UIImage *)crash;
27 |
28 | + (UIImage *)memoryWarning;
29 |
30 | + (UIImage *)border;
31 |
32 | + (UIImage *)viewClass;
33 |
34 | + (UIImage *)image;
35 |
36 | + (UIImage *)location;
37 |
38 | + (UIImage *)frameRate;
39 |
40 | + (UIImage *)behaviorLog;
41 |
42 | + (UIImage *)asyncIcon;
43 |
44 | + (UIImage *)colorPickerIcon;
45 |
46 | + (UIImage *)tipIcon;
47 |
48 | + (UIImage *)schemeManagerIcon;
49 |
50 | + (UIImage *)scanIcon;
51 |
52 | + (UIImage *)pluginIcon;
53 |
54 | + (UIImage *)searchBarIcon;
55 |
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorTimer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 |
8 | extern const NSString* kVZTimerReadCallbackString;
9 | extern const NSString* kVZTimerWriteCallbackString;
10 | extern const NSString* kVZTimerStartCallbackString;
11 | extern const NSString* kVZTimerStopCallbackString;
12 |
13 | typedef void(^vz_inspectorTimerReadCallback)(void);
14 | typedef void(^vz_inspectorTimerWriteCallback)(void) ;
15 |
16 | @interface VZInspectorTimer : NSObject
17 |
18 | @property(nonatomic,copy) vz_inspectorTimerReadCallback readCallback;
19 | @property(nonatomic,copy) vz_inspectorTimerWriteCallback writeCallback;
20 |
21 | + (instancetype)sharedInstance;
22 |
23 | - (void)startTimer;
24 |
25 | - (void)stopTimer;
26 |
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorTimer.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorTimer.h"
6 | #import "VZMemoryInspector.h"
7 | #import "VZNetworkInspector.h"
8 | #import "NSObject+VZInspector.h"
9 |
10 |
11 | NSString const* kVZTimerReadCallbackString = @"kVZTimerReadCallbackString";
12 | NSString const* kVZTimerWriteCallbackString = @"kVZTimerWriteCallbackString";
13 | NSString const* kVZTimerStartCallbackString = @"kVZTimerStartCallbackString";
14 | NSString const* kVZTimerStopCallbackString = @"kVZTimerStopCallbackString";
15 |
16 | @interface NSTimer(VZInspector)
17 | +(NSTimer* )scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void(^)(void))block userInfo:(id)userInfo repeats:(BOOL)repeat;
18 | @end
19 |
20 | @implementation NSTimer(VZInspector)
21 |
22 | + (NSTimer* )scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void (^)(void))block userInfo:(id)userInfo repeats:(BOOL)repeat
23 | {
24 | return [NSTimer scheduledTimerWithTimeInterval:ti target:self selector:@selector(onTimerFired:) userInfo:[block copy] repeats:repeat];
25 | }
26 |
27 | + (void)onTimerFired:(NSTimer* )timer
28 | {
29 | void(^block)(void) = timer.userInfo;
30 |
31 | if (block) {
32 | block();
33 | }
34 | }
35 |
36 | @end
37 |
38 | @interface VZInspectorTimer()
39 |
40 | @property(nonatomic,strong)NSTimer* readTimer;
41 | @property(nonatomic,strong)NSTimer* writeTimer;
42 |
43 | @end
44 |
45 | @implementation VZInspectorTimer
46 | {
47 |
48 | }
49 |
50 | + (instancetype)sharedInstance
51 | {
52 | static VZInspectorTimer* instance = nil;
53 | static dispatch_once_t onceToken;
54 | dispatch_once(&onceToken, ^{
55 | instance = [VZInspectorTimer new];
56 | });
57 | return instance;
58 | }
59 |
60 |
61 | - (void)startTimer
62 | {
63 | [[NSNotificationCenter defaultCenter] postNotificationName:(NSString* const)kVZTimerStartCallbackString object:nil];
64 |
65 | __weak typeof(self) weakSelf = self;
66 | [VZInspectorTimer sharedInstance].readTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 block:^{
67 |
68 | //timer
69 | [weakSelf handleRead];
70 |
71 | } userInfo:nil repeats:YES];
72 |
73 | [[NSRunLoop currentRunLoop] addTimer:[VZInspectorTimer sharedInstance].readTimer forMode:NSRunLoopCommonModes];
74 |
75 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
76 |
77 | [VZInspectorTimer sharedInstance].writeTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 block:^{
78 |
79 | //timer
80 | [weakSelf handleWrite];
81 |
82 | } userInfo:nil repeats:YES];
83 |
84 | [[NSRunLoop currentRunLoop] addTimer:[VZInspectorTimer sharedInstance].writeTimer forMode:NSRunLoopCommonModes];
85 |
86 | });
87 | }
88 |
89 | - (void)stopTimer
90 | {
91 | [[NSNotificationCenter defaultCenter] postNotificationName:(NSString* const)kVZTimerStopCallbackString object:nil];
92 |
93 | [[VZInspectorTimer sharedInstance].readTimer invalidate];
94 | [[VZInspectorTimer sharedInstance].writeTimer invalidate];
95 | [VZInspectorTimer sharedInstance].readTimer = nil;
96 | [VZInspectorTimer sharedInstance].writeTimer = nil;
97 | }
98 |
99 | - (void)handleRead
100 | {
101 | [[NSNotificationCenter defaultCenter] postNotificationName:(NSString* const)kVZTimerReadCallbackString object:nil];
102 |
103 | if (self.readCallback) {
104 | self.readCallback();
105 | }
106 | }
107 |
108 | - (void)handleWrite
109 | {
110 | [[NSNotificationCenter defaultCenter] postNotificationName:(NSString* const)kVZTimerWriteCallbackString object:nil];
111 |
112 | if (self.writeCallback) {
113 | self.writeCallback();
114 | }
115 | }
116 |
117 | @end
118 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorUtility.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import
7 |
8 | @class VZNetworkTransaction;
9 |
10 | @interface VZInspectorUtility : NSObject
11 |
12 | + (NSDictionary *)dictionaryFromQuery:(NSString *)query;
13 |
14 | + (NSString *)prettyJSONStringFromData:(NSData *)data;
15 |
16 | + (NSString *)prettyJSONStringFromObject:(id)jsonObject;
17 |
18 | + (NSString *)prettyStringFromRequestBodyForTransaction:(VZNetworkTransaction *)transaction;
19 |
20 | + (NSString *)prettyStringFromResponseBodyForTransaction:(VZNetworkTransaction *)transaction;
21 |
22 | + (NSString *)timestampStringFromRequestDate:(NSDate *)date;
23 |
24 | + (NSString *)stringFromRequestDuration:(NSTimeInterval)duration;
25 |
26 | + (NSString *)statusCodeStringFromURLResponse:(NSURLResponse *)response;
27 |
28 | + (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData;
29 |
30 | + (NSString *)stringFormatFromDate:(NSDate *)date;
31 |
32 | + (UIColor* )themeColor;
33 |
34 | + (UIColor* )blueColor;
35 |
36 | + (UILabel *)simpleLabel:(CGRect)frame f:(int)size tc:(UIColor *)color t:(NSString *)text;
37 |
38 | + (UILabel *)simpleBorderLabel:(CGRect)frame f:(int)size tc:(UIColor *)color t:(NSString *)text;
39 |
40 | + (UIButton *)simpleButton:(CGRect)frame f:(int)size tc:(UIColor *)color t:( NSString *)text;
41 |
42 | + (UIImage *)imageWithColor:(UIColor *)color;
43 |
44 | + (BOOL)validateRegularExpression:(NSString *)pattern string:(NSString *)string;
45 |
46 | + (BOOL)isNumber:(NSString *)string;
47 |
48 | + (UIWindow *)mainWindow ;
49 |
50 | @end
51 |
52 | extern void VZSwapClassMethods(Class cls, SEL original, SEL replacement);
53 |
54 | extern void VZSwapInstanceMethods(Class cls, SEL original, SEL replacement);
55 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorView : UIView
8 |
9 | @property(nonatomic,weak) UIViewController* parentViewController;
10 |
11 | - (id)initWithFrame:(CGRect)frame parentViewController:(UIViewController* )controller;
12 | - (void)update;
13 | - (void)pop;
14 | - (BOOL)canTouchPassThrough:(CGPoint)pt;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @implementation VZInspectorView
8 |
9 | - (id)initWithFrame:(CGRect)frame parentViewController:(UIViewController* )controller
10 | {
11 | self.parentViewController = controller;
12 | return [self initWithFrame:frame];
13 | }
14 |
15 | - (id)initWithFrame:(CGRect)frame
16 | {
17 | self = [super initWithFrame:frame];
18 |
19 | if (self) {
20 |
21 | }
22 | return self;
23 | }
24 |
25 | - (void)update
26 | {
27 | //noop
28 | }
29 |
30 | - (void)pop
31 | {
32 | #pragma clang diagnostic push
33 | #pragma clang diagnostic ignored "-Wundeclared-selector"
34 | [self.parentViewController performSelector:@selector(onBack)];
35 | #pragma clang diagnostic pop
36 | }
37 |
38 | - (BOOL)canTouchPassThrough:(CGPoint)pt
39 | {
40 | return NO;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorWindow.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | #import "VZInspectController.h"
8 |
9 | @interface VZInspectorWindow : UIWindow
10 |
11 |
12 | +(instancetype)sharedInstance;
13 | +(VZInspectController *)sharedController;
14 |
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/VZInspector/core/VZInspectorWindow.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorWindow.h"
6 | #import "VZInspectController.h"
7 |
8 | @interface VZInspectorWindow()
9 |
10 | @property(nonatomic,strong) VZInspectController* debuggerVC;
11 |
12 | @end
13 |
14 | @implementation VZInspectorWindow
15 |
16 |
17 | + (instancetype)sharedInstance
18 | {
19 | static VZInspectorWindow* instance = nil;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | instance = [[VZInspectorWindow alloc]init];
23 | });
24 | return instance;
25 |
26 | }
27 |
28 | + (VZInspectController *)sharedController {
29 | return [[self sharedInstance] debuggerVC];
30 | }
31 |
32 | - (id)init
33 | {
34 | CGRect screenBound = [UIScreen mainScreen].bounds;
35 | self = [super initWithFrame:screenBound];
36 | if (self)
37 | {
38 | self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f];
39 | //self.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.5];
40 | self.hidden = YES;
41 | self.windowLevel = UIWindowLevelStatusBar + 200;
42 | self.userInteractionEnabled = NO;
43 |
44 | self.debuggerVC = [VZInspectController new];
45 | self.rootViewController = self.debuggerVC;
46 | [self addSubview:self.debuggerVC.view];
47 |
48 | }
49 | return self;
50 | }
51 |
52 | - (void)setHidden:(BOOL)hidden
53 | {
54 | [super setHidden:hidden];
55 |
56 | if ( self.hidden )
57 | {
58 | [self.debuggerVC stop];
59 | }
60 | else
61 | {
62 | [self.debuggerVC start];
63 | }
64 | }
65 |
66 |
67 | - (UIView* )hitTest:(CGPoint)point withEvent:(UIEvent *)event
68 | {
69 | CGPoint pt = [self convertPoint:point toView:self.debuggerVC.view];
70 |
71 | if (self.debuggerVC.presentedViewController) {
72 | for (long i = self.subviews.count - 1; i >= 0; i --) {
73 | UIView *subview = self.subviews[i];
74 | CGPoint convertedPoint = [subview convertPoint:point fromView:self];
75 | UIView *hited = [subview hitTest:convertedPoint withEvent:event];
76 | if (hited) {
77 | return hited;
78 | }
79 | }
80 | }
81 | if ([self.debuggerVC canTouchPassThrough:pt]) {
82 | return [super hitTest:point withEvent:event];
83 | }
84 | else
85 | return [self.debuggerVC.view hitTest:point withEvent:event];
86 | // return self.debuggerVC.view;
87 | }
88 |
89 |
90 |
91 |
92 | @end
93 |
--------------------------------------------------------------------------------
/VZInspector/core/item/VZInspectorBizLogItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorBizLogItem : NSObject
8 |
9 | @property (nonatomic, assign) float itemHeight;
10 |
11 | @property (nonatomic, assign) Class cellClass;
12 |
13 | @property (nonatomic, strong) NSIndexPath *indexPath;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/VZInspector/core/item/VZInspectorBizLogItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorBizLogItem.h"
6 |
7 | @implementation VZInspectorBizLogItem
8 |
9 | - (void)encodeWithCoder:(NSCoder *)aCoder{
10 |
11 | [aCoder encodeObject:self.indexPath forKey:@"indexPath"];
12 | [aCoder encodeObject:@(self.itemHeight) forKey:@"itemHeight"];
13 | [aCoder encodeObject:self.cellClass forKey:@"cellClass"];
14 |
15 | }
16 |
17 | - (id)initWithCoder:(NSCoder *)aDecoder
18 | {
19 | self = [self init];
20 | if (self){
21 |
22 | self.indexPath = [aDecoder decodeObjectForKey:@"indexPath"];
23 | self.itemHeight = ((NSNumber*)[aDecoder decodeObjectForKey:@"itemHeight"]).floatValue;
24 | self.cellClass = [aDecoder decodeObjectForKey:@"cellClass"];
25 | }
26 | return self;
27 | }
28 |
29 | - (id)copyWithZone:(NSZone *)zone
30 | {
31 | VZInspectorBizLogItem* item = [[self class] allocWithZone:zone];
32 | item.indexPath = self.indexPath;
33 | item.itemHeight = self.itemHeight;
34 | item.cellClass = self.cellClass;
35 | return item;
36 | }
37 |
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/VZInspector/core/keycommand/VZKeyCommands.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface VZKeyCommands : NSObject
13 |
14 | + (instancetype)sharedInstance;
15 |
16 | /**
17 | * Register a single-press keyboard command.
18 | */
19 | - (void)registerKeyCommandWithInput:(NSString *)input
20 | modifierFlags:(UIKeyModifierFlags)flags
21 | action:(void (^)(UIKeyCommand *command))block;
22 |
23 | /**
24 | * Unregister a single-press keyboard command.
25 | */
26 | - (void)unregisterKeyCommandWithInput:(NSString *)input
27 | modifierFlags:(UIKeyModifierFlags)flags;
28 |
29 | /**
30 | * Check if a single-press command is registered.
31 | */
32 | - (BOOL)isKeyCommandRegisteredForInput:(NSString *)input
33 | modifierFlags:(UIKeyModifierFlags)flags;
34 |
35 | /**
36 | * Register a double-press keyboard command.
37 | */
38 | - (void)registerDoublePressKeyCommandWithInput:(NSString *)input
39 | modifierFlags:(UIKeyModifierFlags)flags
40 | action:(void (^)(UIKeyCommand *command))block;
41 |
42 | /**
43 | * Unregister a double-press keyboard command.
44 | */
45 | - (void)unregisterDoublePressKeyCommandWithInput:(NSString *)input
46 | modifierFlags:(UIKeyModifierFlags)flags;
47 |
48 | /**
49 | * Check if a double-press command is registered.
50 | */
51 | - (BOOL)isDoublePressKeyCommandRegisteredForInput:(NSString *)input
52 | modifierFlags:(UIKeyModifierFlags)flags;
53 |
54 | @end
--------------------------------------------------------------------------------
/VZInspector/core/manager/VZInspectorBizLogManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZInspectorBizLogView.h"
7 |
8 | @interface VZInspectorBizLogManager : NSObject
9 |
10 | @property (nonatomic, strong) VZInspectorBizLogView *logView;
11 |
12 |
13 | + (instancetype)sharedInstance ;
14 |
15 | - (void)show;
16 |
17 | - (void)hide;
18 |
19 | - (void)toggle;
20 |
21 | - (void)onClickClearButton;
22 |
23 | - (void)onClickCancleButton;
24 |
25 | - (BOOL)isShowing;
26 | @end
27 |
--------------------------------------------------------------------------------
/VZInspector/core/manager/VZInspectorBizLogManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorBizLogManager.h"
6 |
7 | @interface VZInspectorBizLogManager()
8 |
9 | @property (nonatomic, assign) CGRect logViewFrameBeforeDragging;
10 |
11 | @end
12 |
13 | @implementation VZInspectorBizLogManager{
14 | BOOL _isShowing;
15 | }
16 |
17 | + (instancetype)sharedInstance {
18 | static VZInspectorBizLogManager *_manager = nil;
19 | static dispatch_once_t onceToken;
20 | dispatch_once(&onceToken, ^{
21 | _manager = [[VZInspectorBizLogManager alloc] init];
22 | });
23 | return _manager;
24 | }
25 |
26 |
27 | - (void)toggle{
28 | if(_isShowing){
29 | [self hide];
30 | }else {
31 | [self show];
32 | }
33 | }
34 |
35 | - (void)show{
36 | if(!_isShowing){
37 | if(self.logView){
38 | self.logView.delegate = self;
39 | [[UIApplication sharedApplication].keyWindow addSubview:self.logView];
40 | }
41 | }
42 | _isShowing = YES;
43 | }
44 |
45 | - (void)hide{
46 | if(self.logView){
47 | [self.logView removeFromSuperview];
48 | self.logView.delegate = nil;
49 | }
50 | _isShowing = NO;
51 | }
52 |
53 | - (BOOL)isShowing{
54 | return _isShowing;
55 | }
56 |
57 | - (void)onClickCancleButton{
58 | //subclass todo
59 | [self hide];
60 | }
61 |
62 | - (void)onClickClearButton{
63 | // subclass todo
64 | }
65 |
66 | - (void)dragLogViewPanGesture:(UIPanGestureRecognizer *)pan {
67 | if(self.logView){
68 | switch (pan.state) {
69 | case UIGestureRecognizerStateBegan:
70 | self.logViewFrameBeforeDragging = self.logView.frame;
71 | [self updateToolbarPostionWithDragGesture:pan];
72 | break;
73 |
74 | case UIGestureRecognizerStateChanged:
75 | case UIGestureRecognizerStateEnded:
76 | [self updateToolbarPostionWithDragGesture:pan];
77 | break;
78 |
79 | default:
80 | break;
81 | }
82 | }
83 | }
84 |
85 |
86 | - (void)updateToolbarPostionWithDragGesture:(UIPanGestureRecognizer *)pan {
87 |
88 | if(self.logView){
89 | UIView *superView = self.logView.superview;
90 | CGPoint translation = [pan translationInView:superView];
91 | CGRect newlogViewFrame = self.logViewFrameBeforeDragging;
92 | newlogViewFrame.origin.y += translation.y;
93 |
94 | CGFloat maxY = CGRectGetMaxY(superView.bounds) - newlogViewFrame.size.height;
95 | if (newlogViewFrame.origin.y < 0.0) {
96 | newlogViewFrame.origin.y = 0.0;
97 | } else if (newlogViewFrame.origin.y > maxY) {
98 | newlogViewFrame.origin.y = maxY;
99 | }
100 |
101 | self.logView.frame = newlogViewFrame;
102 | }
103 | }
104 |
105 | @end
106 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorBizLogCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZInspectorBizLogItem.h"
7 |
8 | @interface VZInspectorBizLogCell : UITableViewCell
9 |
10 | /**
11 | * cell的index
12 | */
13 | @property (nonatomic,strong) NSIndexPath* indexPath;
14 | /**
15 | * cell绑定的item数据
16 | */
17 | @property (nonatomic,strong) VZInspectorBizLogItem* item;
18 |
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorBizLogCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorBizLogCell.h"
6 |
7 | @implementation VZInspectorBizLogCell
8 |
9 |
10 | - (void)setItem:(VZInspectorBizLogItem *)item{
11 | _item = item;
12 | }
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorBizLogToolBarItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import
7 |
8 | @interface VZInspectorBizLogToolBarItem : NSObject
9 |
10 | @property(nonatomic, strong)NSString *normalTitle;
11 |
12 | @property(nonatomic, strong)NSString *selectedTitle;
13 |
14 | @property(nonatomic, strong)UIColor *normalTitleColor;
15 |
16 | @property(nonatomic, strong)UIColor *selectedTitleColor;
17 |
18 | @property(nonatomic, strong)UIColor *normalBackgroundColor;
19 |
20 | @property(nonatomic, strong)UIColor *selectedbackgroundColor;
21 |
22 | @property(nonatomic, strong)UIColor *normalBorderColor;
23 |
24 | @property(nonatomic, strong)UIColor *selectedBorderColor;
25 |
26 | @property(nonatomic, assign)BOOL isSelected;
27 |
28 | //这里不会有其他其他状态的改变,只会把当前点击的返回
29 | @property(nonatomic, assign)BOOL onlyClick;
30 |
31 | @property(nonatomic, assign) NSUInteger type;
32 |
33 | // groupId 为0 表示互不影响,可以共存, 如果groupId > 0 ,则按groupId分组,分组内的东西互斥
34 | @property(nonatomic, assign) NSUInteger groupId;
35 |
36 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type isSelected:(BOOL)isSelected groupId:(NSUInteger)groupId;
37 |
38 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type isSelected:(BOOL)isSelected;
39 |
40 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type onlyClick:(BOOL)onlyClick;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorBizLogToolBarItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorBizLogToolBarItem.h"
6 | #import "VZDefine.h"
7 |
8 | @implementation VZInspectorBizLogToolBarItem
9 |
10 | - (instancetype)init{
11 | if(self = [super init]){
12 | _normalTitleColor = VZ_RGB(0x000000);
13 | _normalBackgroundColor = VZ_RGB(0xffffff);
14 | _normalBorderColor = VZ_RGB(0xbdc8d0);
15 | _selectedBorderColor = VZ_INSPECTOR_MAIN_COLOR;
16 | _groupId = 0;
17 | }
18 | return self;
19 | }
20 |
21 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type isSelected:(BOOL)isSelected groupId:(NSUInteger)groupId{
22 | VZInspectorBizLogToolBarItem *item = [VZInspectorBizLogToolBarItem new];
23 | item.normalTitle = normalTitle;
24 | item.selectedTitle = selectedTitle;
25 | item.isSelected = isSelected;
26 | item.groupId = groupId;
27 | item.type = type;
28 |
29 | return item;
30 | }
31 |
32 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type isSelected:(BOOL)isSelected{
33 | return [self.class normalToolBarItemWithNormalTitle:normalTitle selectedTitle:selectedTitle type:type isSelected:isSelected groupId:0];
34 | }
35 |
36 | + (VZInspectorBizLogToolBarItem *)normalToolBarItemWithNormalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle type:(NSUInteger)type onlyClick:(BOOL)onlyClick{
37 | VZInspectorBizLogToolBarItem *item = [self.class normalToolBarItemWithNormalTitle:normalTitle selectedTitle:selectedTitle type:type isSelected:NO groupId:0];
38 | item.onlyClick = onlyClick;
39 | return item;
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorBizLogView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZInspectorBizLogItem.h"
7 | #import "VZInspectorBizLogToolBarItem.h"
8 | #import "VZInspectorTagListView.h"
9 | #import "VZInspectorSearchBar.h"
10 |
11 | @protocol VZInspectorBizLogViewDelegate
12 |
13 | @optional
14 | - (void)onClickCancleButton;
15 | - (void)onClickClearButton;
16 |
17 | @end
18 |
19 | @interface VZInspectorBizLogView : UIView
20 |
21 | @property (nonatomic , weak) id delegate;
22 |
23 | @property (nonatomic, strong) NSMutableArray *items;
24 |
25 | @property (nonatomic, strong) UITableView *tableView;
26 |
27 | @property (nonatomic, strong) UIView *headerView;
28 |
29 | @property (nonatomic, strong) UILabel *dragView;
30 |
31 | @property (nonatomic, strong) VZInspectorSearchBar *searchView;
32 |
33 | @property (nonatomic, strong) VZInspectorTagListView *tagListView;
34 |
35 | @property (nonatomic, strong) UIView *searchBarBackgroundView;
36 |
37 | @property (nonatomic, strong) NSString *title;
38 |
39 | @property (nonatomic, strong) NSString *leftButtonTitle;
40 |
41 | @property (nonatomic, strong) NSString *rightButtonTitle;
42 |
43 | @property (nonatomic, assign) BOOL hasSearchBar;
44 |
45 | @property (nonatomic,strong) NSArray *toolBarItems;
46 |
47 | @property (nonatomic, strong)VZInspectorTagViewTap tagViewTapListener;
48 |
49 | - (void)reloadDatas;
50 |
51 | - (void)setToolBarHidden:(BOOL)hidden;
52 |
53 | - (VZInspectorBizLogItem *)itemForCellAtIndexPath:(NSIndexPath *)indexPath;
54 |
55 | - (void)addDragTagGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;
56 |
57 | -(void)textFieldTextDidChange:(UITextField *)textField;
58 |
59 | - (void)leftButtonClick;
60 |
61 | - (void)rightButtonClick;
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorMaskView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @protocol VZInspectorMaskViewCancleDelegate
8 |
9 | @optional
10 |
11 | - (void)cancleMaskView;
12 |
13 | @end
14 |
15 | @interface VZInspectorMaskView : UIView
16 |
17 | @property (nonatomic, strong) UIView *rootView;
18 |
19 | @property (nonatomic, weak) id delegate;
20 |
21 |
22 | /**
23 | * 背景view
24 | */
25 | @property (nonatomic, strong) UIView *backgroudView;
26 |
27 | /**
28 | * 内容view
29 | */
30 | @property (nonatomic, strong) UIView *contentView;
31 |
32 |
33 | /**
34 | * 点击内容区外的区域取消蒙层 ,默认为NO;
35 | */
36 | @property (nonatomic, assign) BOOL canceledOnTouchOutside;
37 |
38 |
39 | - (instancetype)initWithFrame:(CGRect)frame rootView:(UIView *)rootView ;
40 |
41 |
42 | /**
43 | * 蒙层是否正在显示
44 | *
45 | */
46 | - (BOOL)isShowing;
47 |
48 | /**
49 | * 隐藏蒙层
50 | */
51 | - (void)hideMaskView;
52 |
53 | /**
54 | * 显示蒙层
55 | */
56 | - (void)showMaskView;
57 |
58 | /**
59 | * 开始布局蒙层里面的视图
60 | */
61 | - (void)layoutMaskviews;
62 |
63 | - (void)removeFromSuperview;
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorMaskView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorMaskView.h"
6 | #import "VZDefine.h"
7 | #import
8 |
9 | @implementation VZInspectorMaskView{
10 | BOOL _showing;
11 | CGRect _contentFrame;
12 | CGRect _rootFrame ;
13 |
14 | }
15 |
16 | - (instancetype)initWithFrame:(CGRect)frame rootView:(UIView *)rootView{
17 | if(self = [super init]){
18 | _contentFrame = frame;
19 | _rootFrame = rootView.frame;
20 | _contentView = [[UIView alloc]initWithFrame:frame];
21 | _backgroudView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _rootFrame.size.width, _rootFrame.size.height)];
22 | _backgroudView.backgroundColor = VZ_RGBA(0x000000, 0.68);
23 |
24 | _contentView.center = CGPointMake(_rootFrame.size.width/2, _rootFrame.size.height/2);
25 | _contentFrame = _contentView.frame;
26 |
27 | [_backgroudView addSubview:_contentView];
28 |
29 | [_backgroudView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapBackgroundView)]];
30 |
31 | _rootView = rootView;
32 | _showing = NO;
33 | _canceledOnTouchOutside = NO;
34 | [self layoutMaskviews];
35 | }
36 |
37 | return self;
38 | }
39 |
40 | - (void)setCanceledOnTouchOutside:(BOOL)canceledOnTouchOutside{
41 | if(canceledOnTouchOutside){
42 | _backgroudView.userInteractionEnabled = YES;
43 | }else{
44 | _backgroudView.userInteractionEnabled = NO;
45 | }
46 | _canceledOnTouchOutside = canceledOnTouchOutside;
47 | }
48 |
49 | - (void)setBackgroudView:(UIView *)backgroudView{
50 | if(_backgroudView){
51 | [_contentView removeFromSuperview];
52 | [_backgroudView removeFromSuperview];
53 | }
54 | _backgroudView = backgroudView;
55 | [_backgroudView addSubview:_contentView];
56 | }
57 |
58 | - (void)tapBackgroundView{
59 | if(_canceledOnTouchOutside){
60 | if([self.delegate respondsToSelector:@selector(cancleMaskView)]){
61 | [self.delegate cancleMaskView];
62 | }
63 | }
64 | }
65 |
66 | - (void)hideMaskView{
67 | if (_rootView && _backgroudView) {
68 |
69 | [UIView animateWithDuration:0.3 animations:^{
70 | self->_backgroudView.alpha = 0.0;
71 |
72 | } completion:^(BOOL finished) {
73 | [self->_backgroudView removeFromSuperview];
74 | self->_showing = NO;
75 | }];
76 | }
77 | }
78 |
79 | - (void)showMaskView{
80 | if(_rootView && _backgroudView){
81 | [_backgroudView removeFromSuperview];
82 | _backgroudView.alpha = 1;
83 | [_rootView addSubview:_backgroudView];
84 | [_rootView bringSubviewToFront:_backgroudView];
85 | _showing = YES;
86 | }
87 | }
88 |
89 | - (void)removeFromSuperview{
90 | if(_rootView && _backgroudView){
91 | [_backgroudView removeFromSuperview];
92 | _showing = NO;
93 | }
94 | }
95 |
96 | - (BOOL)isShowing{
97 | return _showing;
98 | }
99 |
100 | - (void)layoutMaskviews{
101 | //subClass todo
102 | }
103 |
104 | @end
105 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorSearchBar.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorSearchBar : UITextField
8 |
9 | @property (nonatomic, assign) UIEdgeInsets edgeInsets;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorSearchBar.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorSearchBar.h"
6 |
7 | @implementation VZInspectorSearchBar
8 |
9 | - (CGRect)textRectForBounds:(CGRect)bounds
10 | {
11 | return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, _edgeInsets)];
12 | }
13 |
14 | - (CGRect)editingRectForBounds:(CGRect)bounds
15 | {
16 | return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, _edgeInsets)];
17 | }
18 |
19 | - (CGRect)leftViewRectForBounds:(CGRect)bounds{
20 | return [super leftViewRectForBounds:UIEdgeInsetsInsetRect(bounds, _edgeInsets)];
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorTagListView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TagListView.h
3 | // TagObjc
4 | //
5 | // Created by Javi Pulido on 16/7/15.
6 | // Copyright (c) 2015 Javi Pulido. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "VZInspectorBizLogToolBarItem.h"
11 |
12 | @class VZInspectorTagView;
13 |
14 | typedef void (^VZInspectorTagViewTap)(NSArray *);
15 |
16 |
17 | @interface VZInspectorTagListView : UIView
18 |
19 | @property (nonatomic) UIColor *textColor;
20 | @property (nonatomic) UIColor *tagBackgroundColor;
21 | @property (nonatomic) CGFloat cornerRadius;
22 | @property (nonatomic) CGFloat borderWidth;
23 | @property (nonatomic) UIColor *borderColor;
24 | @property (nonatomic) CGFloat paddingY;
25 | @property (nonatomic) CGFloat paddingX;
26 | @property (nonatomic) CGFloat marginY;
27 | @property (nonatomic) CGFloat marginX;
28 | @property (nonatomic) UIFont *textFont;
29 |
30 |
31 | @property (nonatomic) CGFloat tagViewHeight;
32 | @property (nonatomic ,assign)CGFloat frameHeight;
33 | @property (nonatomic) NSMutableArray *tagViews;
34 | @property (nonatomic) int rows;
35 |
36 | @property (nonatomic ,strong)VZInspectorTagViewTap tagViewTap;
37 |
38 | - (void)addTagItems:(NSArray *)tagItems;
39 | - (void)removeTag:(NSString *)title;
40 | - (void)removeAllTags;
41 |
42 | - (void)setSelectedTagView:(VZInspectorTagView *)tagView;
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorTagView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TagView.h
3 | // TagObjc
4 | //
5 | // Created by Javi Pulido on 16/7/15.
6 | // Copyright (c) 2015 Javi Pulido. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "VZInspectorBizLogToolBarItem.h"
11 |
12 | @interface VZInspectorTagView : UIButton
13 |
14 | - (instancetype) initWithTitle:(NSString *)title;
15 |
16 | @property (nonatomic) CGFloat cornerRadius;
17 | @property (nonatomic) CGFloat borderWidth;
18 | @property (nonatomic) UIColor *borderColor;
19 | @property (nonatomic) UIColor *textColor;
20 | @property (nonatomic) CGFloat paddingY;
21 | @property (nonatomic) CGFloat paddingX;
22 | @property (nonatomic) UIFont *textFont;
23 |
24 | @property (nonatomic , strong) VZInspectorBizLogToolBarItem *item;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/VZInspector/core/view/VZInspectorTagView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TagView.m
3 | // TagObjc
4 | //
5 | // Created by Javi Pulido on 16/7/15.
6 | // Copyright (c) 2015 Javi Pulido. All rights reserved.
7 | //
8 |
9 | #import "VZInspectorTagView.h"
10 |
11 |
12 |
13 | @implementation VZInspectorTagView{
14 | BOOL _hasCalculateSize;
15 | CGSize _textCalculateSize;
16 | }
17 |
18 | @synthesize textColor =_textColor;
19 | @synthesize textFont = _textFont;
20 |
21 | - (instancetype) initWithTitle:(NSString *)title {
22 | self = [super init];
23 | if(self) {
24 | _hasCalculateSize = NO;
25 | [self setTitle:title forState:UIControlStateNormal];
26 | CGSize intrinsicSize = [self intrinsicContentSize];
27 | self.frame = CGRectMake(0, 0, intrinsicSize.width, intrinsicSize.height);
28 | }
29 | return self;
30 | }
31 |
32 | - (CGSize) intrinsicContentSize {
33 |
34 | if(_hasCalculateSize){
35 | return _textCalculateSize;
36 | }
37 |
38 |
39 | CGSize size = [self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: self.titleLabel.font}];
40 |
41 | size.height = self.titleLabel.font.pointSize + self.paddingY * 2;
42 | size.width += self.paddingX * 2;
43 |
44 | _hasCalculateSize = YES;
45 | _textCalculateSize = size;
46 | return size;
47 | }
48 |
49 | # pragma mark - Getters
50 |
51 | - (UIColor *)textColor {
52 | if(!self.textColor) {
53 | self.textColor = [UIColor blackColor];
54 | }
55 | return self.textColor;
56 | }
57 |
58 | - (UIFont *)textFont {
59 | if(!self.textFont) {
60 | self.textFont = [UIFont systemFontOfSize:12];
61 | }
62 | return self.textFont;
63 | }
64 |
65 | # pragma mark - Setters
66 |
67 | - (void)setCornerRadius:(CGFloat)cornerRadius {
68 | _cornerRadius = cornerRadius;
69 | self.layer.cornerRadius = cornerRadius;
70 | self.layer.masksToBounds = self.cornerRadius > 0;
71 | }
72 |
73 | - (void)setBorderWidth:(CGFloat)borderWidth {
74 | _borderWidth = borderWidth;
75 | self.layer.borderWidth = borderWidth;
76 |
77 | }
78 |
79 | - (void)setBorderColor:(UIColor *)borderColor {
80 | _borderColor = borderColor;
81 | self.layer.borderColor = borderColor.CGColor;
82 | }
83 |
84 | - (void)setTextColor:(UIColor *)textColor {
85 | _textColor = textColor;
86 | [self setTitleColor:textColor forState:UIControlStateNormal];
87 | }
88 |
89 | - (void)setPaddingY:(CGFloat)paddingY {
90 | _paddingY = paddingY;
91 | UIEdgeInsets insets = [self titleEdgeInsets];
92 | insets.top = paddingY;
93 | insets.bottom = paddingY;
94 | [self setTitleEdgeInsets:insets];
95 | }
96 |
97 | - (void)setPaddingX:(CGFloat)paddingX {
98 | _paddingX = paddingX;
99 | UIEdgeInsets insets = [self titleEdgeInsets];
100 | insets.left = paddingX;
101 | insets.right = paddingX;
102 | [self setTitleEdgeInsets:insets];
103 | }
104 |
105 | - (void)setTextFont:(UIFont *)textFont {
106 | _textFont = textFont;
107 | _hasCalculateSize = NO;
108 | [self.titleLabel setFont:textFont];
109 | }
110 |
111 | @end
112 |
--------------------------------------------------------------------------------
/VZInspector/log/VZInspectorLogView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorLogView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/log/VZLogInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | #define kVZDefaultNumberOfLogs 20
8 |
9 | @class VZLogInspectorEntity;
10 | @protocol VZLogInspectorDelegate
11 |
12 | - (void)logMessage:(VZLogInspectorEntity *)message;
13 |
14 | @end
15 |
16 | @interface VZLogInspectorEntity:NSObject
17 |
18 | @property (nonatomic, strong) NSDate *date;
19 | @property (nonatomic, copy) NSString *sender;
20 | @property (nonatomic, copy) NSString *messageText;
21 | @property (nonatomic, assign) long long messageID;
22 | @property (nonatomic, assign) NSUInteger level;
23 | @end
24 |
25 | @interface VZLogInspector : NSObject
26 |
27 | @property(nonatomic,copy) NSArray *searchList;
28 |
29 | + (instancetype) sharedInstance;
30 |
31 | @property (nonatomic, strong) NSMutableArray *observers;
32 |
33 | @property (nonatomic, assign) id delegate;
34 |
35 | + (void)setNumberOfLogs:(NSUInteger)num;
36 |
37 | + (NSArray* )logs;
38 |
39 | + (NSAttributedString* )logsString:(NSString *)searchkey;
40 |
41 | +(NSAttributedString *)formatLog:(VZLogInspectorEntity *)entity searchkey:(NSString *)searchKey;
42 |
43 | + (void)start;
44 |
45 | + (void)stop;
46 |
47 | - (void)addObserver:(id)observer;
48 |
49 | - (void)removeObserver:(id)observer;
50 | @end
51 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZInspectorOverview.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 |
8 | @interface VZInspectorOverview : VZInspectorView
9 |
10 | @property(nonatomic,assign) BOOL memoryWarning;
11 |
12 | - (void)updateGlobalInfo;
13 |
14 | - (void)startTimer;
15 |
16 | - (void)stopTimer;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZInspectorOverview.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorOverview.h"
6 | #import "VZMemoryInspectorOverView.h"
7 | #import "VZMemoryInspector.h"
8 | #import "VZInspectorTimer.h"
9 | #import "VZOverviewInspector.h"
10 | #import "NSObject+VZInspector.h"
11 | #import "VZBorderInspector.h"
12 | #import "VZInspectorSettingView.h"
13 | #import "VZControllerStack.h"
14 |
15 | #import
16 |
17 | @interface VZInspectorOverview()
18 |
19 | @property(nonatomic,strong) VZMemoryInspectorOverView* memoryView;
20 | @property(nonatomic, strong) VZInspectorSettingView* settingView;
21 | @property(nonatomic,strong) UITextView* infoView;
22 | @property(nonatomic,strong) UIButton* refreshBtn;
23 |
24 | @end
25 |
26 |
27 | @implementation VZInspectorOverview
28 |
29 | - (id)initWithFrame:(CGRect)frame
30 | {
31 | self = [super initWithFrame:frame];
32 | if (self) {
33 | CGFloat width = self.frame.size.width;
34 |
35 | //envView
36 | CGRect envFrame;
37 | envFrame.origin = CGPointMake(0, 10);
38 | envFrame.size.width = width;
39 | envFrame.size.height = [VZInspectorSettingView heightForEnvButtons];
40 | _settingView = [[VZInspectorSettingView alloc]initWithFrame:CGRectInset(envFrame, 10, 0) parentViewController:self.parentViewController];
41 | [self addSubview:_settingView];
42 |
43 | //total memory
44 | CGRect memoryFrame;
45 | memoryFrame.origin = CGPointMake(0, CGRectGetMaxY(_settingView.frame) + 10);
46 | memoryFrame.size.width = width;
47 | memoryFrame.size.height = 65;
48 |
49 | _memoryView = [[VZMemoryInspectorOverView alloc] initWithFrame:memoryFrame];
50 | [self addSubview:_memoryView];
51 |
52 | //infoView
53 | CGRect infoFrame;
54 | infoFrame.origin = CGPointMake(0, CGRectGetMaxY(_memoryView.frame) - 1);
55 | infoFrame.size.width = width;
56 | infoFrame.size.height = frame.size.height - infoFrame.origin.y;
57 |
58 | _infoView = [[UITextView alloc] initWithFrame:CGRectInset(infoFrame, 10, 10)];
59 | _infoView.font = [UIFont fontWithName:@"Courier-Bold" size:14];
60 | _infoView.textColor = [UIColor orangeColor];
61 | _infoView.indicatorStyle = 0;
62 | _infoView.editable = NO;
63 | _infoView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
64 | _infoView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f];
65 | [self addSubview:_infoView];
66 |
67 | _refreshBtn = [[UIButton alloc]initWithFrame:CGRectMake(CGRectGetMaxX(_infoView.frame) - 54, CGRectGetMaxY(_infoView.frame)-54, 44, 44)];
68 | _refreshBtn.layer.cornerRadius = 22;
69 | _refreshBtn.layer.masksToBounds = true;
70 | _refreshBtn.layer.borderColor = [UIColor grayColor].CGColor;
71 | _refreshBtn.layer.borderWidth = 2.0f;
72 | [_refreshBtn setTitle:@"R" forState:UIControlStateNormal];
73 | [_refreshBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
74 | [_refreshBtn addTarget:self action:@selector(updateGlobalInfo) forControlEvents:UIControlEventTouchUpInside];
75 | [self addSubview:_refreshBtn];
76 |
77 | [self updateGlobalInfo];
78 |
79 | //start timer
80 | __weak typeof(self) weakSelf = self;
81 | [VZInspectorTimer sharedInstance].readCallback = ^{
82 | [weakSelf handleRead];
83 | };
84 |
85 | [VZInspectorTimer sharedInstance].writeCallback = ^{
86 | [[NSNotificationCenter defaultCenter] postNotificationName:(NSString* const)kVZTimerWriteCallbackString object:nil];
87 | [weakSelf handleWrite];
88 | };
89 | }
90 |
91 | return self;
92 | }
93 |
94 | - (void)dealloc
95 | {
96 | [[VZInspectorTimer sharedInstance] stopTimer];
97 | }
98 |
99 | - (void)updateGlobalInfo
100 | {
101 | NSMutableString *text = [NSMutableString new];
102 | for (vz_overview_callback callback in [VZOverviewInspector sharedInstance].observingCallbacks) {
103 | [text appendString:callback()];
104 | [text appendString:@"\n\n"];
105 | }
106 | [text appendFormat:@"Controller Stacks:\n%@", [VZControllerStack controllerStack]];
107 | _infoView.text = text;
108 | }
109 |
110 | - (void)startTimer
111 | {
112 | [[VZInspectorTimer sharedInstance] startTimer];
113 | }
114 |
115 | - (void)stopTimer
116 | {
117 | [[VZInspectorTimer sharedInstance] stopTimer];
118 | }
119 |
120 |
121 | - (void)handleRead
122 | {
123 | [self.memoryView handleRead];
124 | // [self.cpuView handleRead];
125 | // [self.httpView handleRead];
126 |
127 | if (self.memoryWarning) {
128 |
129 | if (self.memoryView.backgroundColor == [[UIColor redColor] colorWithAlphaComponent:0.6f]) {
130 | self.memoryView.backgroundColor = [UIColor clearColor];
131 | }
132 | else
133 | self.memoryView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.6f];
134 |
135 | [VZMemoryInspector performLowMemoryWarning];
136 |
137 | }
138 | else
139 | {
140 | self.memoryView.backgroundColor = [UIColor clearColor];
141 | }
142 |
143 | }
144 | - (void)handleWrite
145 | {
146 | [self.memoryView handleWrite];
147 | // [self.cpuView handleWrite];
148 | // [self.httpView handleWrite];
149 | }
150 |
151 |
152 | - (void)close:(id)sender
153 | {
154 | #pragma clang diagnostic push
155 | #pragma clang diagnostic ignored "-Wundeclared-selector"
156 | [self.parentViewController performSelector:@selector(onClose)];
157 | #pragma clang pop
158 | }
159 |
160 |
161 |
162 |
163 | @end
164 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZInspectorPlotView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorPlotView : UIView
8 |
9 | @property (nonatomic, assign) BOOL fill;
10 | @property (nonatomic, assign) BOOL border;
11 | @property (nonatomic, assign) CGFloat lineScale;
12 | @property (nonatomic, retain) UIColor * lineColor;
13 | @property (nonatomic, assign) CGFloat lineWidth;
14 | @property (nonatomic, assign) CGFloat lowerBound;
15 | @property (nonatomic, assign) CGFloat upperBound;
16 | @property (nonatomic, assign) NSUInteger capacity;
17 | @property (nonatomic, retain) NSArray * plots;
18 | @property (nonatomic, assign) CGFloat dot;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZInspectorPlotView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorPlotView.h"
6 |
7 | @implementation VZInspectorPlotView
8 |
9 | - (id)initWithFrame:(CGRect)frame
10 | {
11 | self = [super initWithFrame:frame];
12 | if (self)
13 | {
14 | self.backgroundColor = [UIColor clearColor];
15 |
16 | self.fill = YES;
17 | self.border = YES;
18 | self.lineScale = 0.8f;
19 | self.lineColor = [UIColor whiteColor];
20 | self.lineWidth = 2.0f;
21 | self.lowerBound = 0.0f;
22 | self.upperBound = 1.0f;
23 | self.capacity = 50;
24 | }
25 | return self;
26 | }
27 |
28 | - (void)dealloc
29 | {
30 | _lineColor = nil;
31 | _plots = nil;
32 | }
33 |
34 | - (void)drawRect:(CGRect)rect
35 | {
36 | [super drawRect:rect];
37 |
38 | CGContextRef context = UIGraphicsGetCurrentContext();
39 | if ( context )
40 | {
41 | CGContextClearRect( context, self.bounds );
42 |
43 | if ( self.fill )
44 | {
45 | CGRect bound = CGRectInset( self.bounds, 4.0f, 2.0f );
46 | CGPoint baseLine;
47 | baseLine.x = bound.origin.x;
48 | baseLine.y = bound.origin.y + bound.size.height;
49 |
50 | UIBezierPath * pathLines = [UIBezierPath bezierPath];
51 | [pathLines moveToPoint:baseLine];
52 |
53 | NSUInteger step = 0;
54 |
55 | for ( NSNumber * value in [_plots copy] )
56 | {
57 | CGFloat v = value.floatValue;
58 |
59 | if ( v < _lowerBound )
60 | {
61 | v = _lowerBound;
62 | }
63 | else if ( v > _upperBound )
64 | {
65 | v = _upperBound;
66 | }
67 |
68 | CGFloat f = (v - _lowerBound) / (_upperBound - _lowerBound) * _lineScale;
69 | CGPoint p = CGPointMake( baseLine.x, baseLine.y - bound.size.height * f );
70 | [pathLines addLineToPoint:p];
71 |
72 | baseLine.x += bound.size.width / _capacity;
73 |
74 | step += 1;
75 | if ( step >= _capacity )
76 | break;
77 | }
78 |
79 | [self.lineColor set];
80 |
81 | [pathLines addLineToPoint:baseLine];
82 | // [pathLines fill];
83 | [pathLines fillWithBlendMode:kCGBlendModeXOR alpha:0.6f];
84 | }
85 |
86 | if ( self.border )
87 | {
88 | CGRect bound = CGRectInset( self.bounds, 4.0f, 2.0f );
89 | CGPoint baseLine;
90 | baseLine.x = bound.origin.x;
91 | baseLine.y = bound.origin.y + bound.size.height;
92 |
93 | CGContextMoveToPoint( context, baseLine.x, baseLine.y );
94 |
95 | NSUInteger step = 0;
96 |
97 | for ( NSNumber * value in [_plots copy] )
98 | {
99 | CGFloat v = value.floatValue;
100 |
101 | if ( v < _lowerBound )
102 | {
103 | v = _lowerBound;
104 | }
105 | else if ( v > _upperBound )
106 | {
107 | v = _upperBound;
108 | }
109 |
110 | CGFloat f = (v - _lowerBound) / (_upperBound - _lowerBound) * _lineScale;
111 | CGPoint p = CGPointMake( baseLine.x, baseLine.y - bound.size.height * f );
112 |
113 | CGContextAddLineToPoint( context, p.x, p.y );
114 |
115 | // if (v == _upperBound) {
116 | // [[UIColor redColor] set];
117 | // [@"top" drawAtPoint:p withFont:[UIFont systemFontOfSize:13]];
118 | // }
119 | CGContextSetStrokeColorWithColor( context, self.lineColor.CGColor );
120 | CGContextSetLineWidth( context, self.lineWidth );
121 | CGContextSetLineCap( context, kCGLineCapRound );
122 | CGContextSetLineJoin( context, kCGLineJoinRound );
123 | CGContextStrokePath( context );
124 |
125 | CGContextMoveToPoint( context, p.x, p.y );
126 | baseLine.x += bound.size.width / _capacity;
127 |
128 | step += 1;
129 | if ( step >= _capacity )
130 | break;
131 | }
132 | }
133 | }
134 | }
135 |
136 |
137 | @end
138 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZOverviewInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 |
8 | typedef NSString*(^vz_overview_callback)(void);
9 | @interface VZOverviewInspector : NSObject
10 |
11 | + (VZOverviewInspector* )sharedInstance;
12 |
13 | @property(nonatomic,copy) NSMutableArray *observingCallbacks;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/VZInspector/overview/VZOverviewInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZOverviewInspector.h"
6 |
7 |
8 | @interface VZOverviewInspector()
9 |
10 | @end
11 |
12 | @implementation VZOverviewInspector
13 |
14 | - (instancetype)init {
15 | if (self = [super init]) {
16 | _observingCallbacks = [NSMutableArray array];
17 | }
18 | return self;
19 | }
20 |
21 | + (VZOverviewInspector* )sharedInstance
22 | {
23 | static VZOverviewInspector* instance = nil;
24 |
25 | static dispatch_once_t onceToken;
26 | dispatch_once(&onceToken, ^{
27 | instance = [VZOverviewInspector new];
28 | });
29 |
30 | return instance;
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/VZInspector/overview/controller/VZControllerStack.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZControllerStack : NSObject
8 |
9 | + (NSString *)controllerStack;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/VZInspector/overview/controller/VZControllerStack.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZControllerStack.h"
7 |
8 | @implementation VZControllerStack
9 |
10 | + (NSString *)controllerStack
11 | {
12 | UIViewController *vc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
13 | return [self controllerStackWithController:vc indent:0];
14 | }
15 |
16 | + (NSString *)controllerStackWithController:(UIViewController *)vc indent:(int)indent
17 | {
18 | if (!vc) {
19 | return @"";
20 | }
21 | NSMutableString *mutableResult = [NSMutableString string];
22 | for (int i = 0; i < indent - 1; i ++) {
23 | [mutableResult appendString:@" |"];
24 | }
25 | [mutableResult appendString:indent == 0 ? @"" : vc.presentingViewController.presentedViewController == vc ? @" +" : @" |"];
26 | [mutableResult appendString:[self descriptionForVc:vc]];
27 | indent += 1;
28 | for (UIViewController *childVc in vc.childViewControllers) {
29 | [mutableResult appendString:[self controllerStackWithController:childVc indent:indent]];
30 | }
31 | if (vc.presentedViewController.presentingViewController == vc) {
32 | [mutableResult appendString:[self controllerStackWithController:vc.presentedViewController indent:indent]];
33 | }
34 | return mutableResult;
35 | }
36 |
37 | + (NSString *)descriptionForVc:(UIViewController *)vc
38 | {
39 | int state = [[vc valueForKey:@"_appearState"] intValue];
40 | NSString *appearState = nil;
41 | switch (state) {
42 | case 0:
43 | appearState = @"disappeared";
44 | break;
45 | case 1:
46 | appearState = @"will appear";
47 | break;
48 | case 2:
49 | appearState = @"appeared";
50 | break;
51 | default:
52 | appearState = @"";
53 | break;
54 | }
55 |
56 | return [NSString stringWithFormat:@"<%@ %@>\n", vc.class, vc.isViewLoaded ? appearState : @"not loaded"];
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/VZInspector/overview/device/VZDevice.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZDevice : NSObject
8 |
9 | + (NSString *)systemVersion;
10 | + (NSString *)systemName;
11 | + (NSString *)name;
12 | + (NSString *)model;
13 | + (NSString *)locationAuth;
14 | + (NSString *)uuid;
15 |
16 | + (NSString *)networkType;
17 | + (NSArray *)infoArray;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/VZInspector/overview/env/VZInspectorSettingView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorSettingView : VZInspectorView
8 |
9 | + (CGFloat)heightForEnvButtons;
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/VZInspector/overview/env/VZInspectorSettingView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #include
6 | #import "VZInspectorSettingView.h"
7 | #import "VZSettingInspector.h"
8 |
9 |
10 | @implementation VZInspectorSettingView
11 |
12 | #define cellHeight 40
13 | #define cellColCount 4
14 |
15 | - (id)initWithFrame:(CGRect)frame
16 | {
17 | self = [super initWithFrame:frame];
18 | if (self) {
19 |
20 | NSArray* btns = [VZSettingInspector currentAPIEnvButtons];
21 | int w = CGRectGetWidth(frame)/cellColCount;
22 |
23 | for (int i=0; i
6 |
7 | typedef void(^vz_api_env_callback)(void);
8 | typedef void(^vz_api_env_switch_callback)(void);
9 |
10 | @interface VZSettingInspector : NSObject
11 |
12 | + (VZSettingInspector* )sharedInstance;
13 | + (void)addAPIEnvButtonWithName:(NSString* )type Selected:(BOOL)selected Callback:(vz_api_env_callback)callback;
14 | + (void)addAPIEnvSwitchWithName:(NSString* )type Selected:(BOOL)selected Callback:(vz_api_env_switch_callback)callback;
15 | + (NSArray* )currentAPIEnvButtons;
16 | + (NSArray* )currentAPIEnvSwitches;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/VZInspector/overview/env/VZSettingInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZSettingInspector.h"
6 |
7 | @implementation VZSettingInspector
8 | {
9 | NSMutableArray* _btns;
10 | NSMutableArray* _switches;
11 | }
12 |
13 | + (VZSettingInspector* )sharedInstance
14 | {
15 | static VZSettingInspector* instance = nil;
16 |
17 | static dispatch_once_t onceToken;
18 | dispatch_once(&onceToken, ^{
19 | instance = [VZSettingInspector new];
20 | });
21 |
22 | return instance;
23 | }
24 |
25 | - (id)init
26 | {
27 | self = [super init];
28 |
29 | if (self) {
30 | _btns = [[NSMutableArray alloc]initWithCapacity:3];
31 | _switches = [[NSMutableArray alloc]initWithCapacity:3];
32 |
33 | }
34 | return self;
35 | }
36 |
37 | + (NSArray* )currentAPIEnvButtons
38 | {
39 | return [[VZSettingInspector sharedInstance] -> _btns copy];
40 | }
41 |
42 | + (NSArray* )currentAPIEnvSwitches
43 | {
44 | return [[VZSettingInspector sharedInstance] -> _switches copy];
45 | }
46 |
47 | + (void)addAPIEnvButtonWithName:(NSString* )type Selected:(BOOL)selected Callback:(vz_api_env_callback)callback{
48 |
49 | if (type && callback) {
50 | [[VZSettingInspector sharedInstance] -> _btns addObject:@{type:@[callback,@(selected)]}];
51 | }
52 |
53 | }
54 |
55 | + (void)addAPIEnvSwitchWithName:(NSString *)type Selected:(BOOL)selected Callback:(vz_api_env_switch_callback)callback{
56 |
57 | if (type && callback) {
58 | [[VZSettingInspector sharedInstance] -> _switches addObject:@{type:@[callback,@(selected)]}];
59 | }
60 |
61 | }
62 |
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/VZInspector/overview/memory/VZMemoryInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZMemoryInspector : NSObject
8 |
9 | + (instancetype)sharedInstance;
10 |
11 | #pragma mark- Memory monitor
12 |
13 | /*
14 | * The number of bytes in memory that used
15 | **/
16 | + (unsigned long long)bytesOfUsedMemory;
17 |
18 | /**
19 | * The number of bytes in memory that are free.
20 | */
21 | + (unsigned long long)bytesOfFreeMemory;
22 |
23 | /**
24 | * The total number of bytes of memory.
25 | */
26 | + (unsigned long long)bytesOfTotalMemory;
27 | /**
28 | * Simulate low memory warning
29 | * notice : _performMemoryWarning is private api
30 | */
31 | + (void)performLowMemoryWarning;
32 | /**
33 | * The number of bytes free on disk.
34 | */
35 | + (unsigned long long)bytesOfFreeDiskSpace;
36 | /**
37 | * The total number of bytes of disk space.
38 | */
39 | + (unsigned long long)bytesOfTotalDiskSpace;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/VZInspector/overview/memory/VZMemoryInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZMemoryInspector.h"
6 | #include
7 | #include
8 | #include
9 | #import "NSObject+VZInspector.h"
10 |
11 | @interface VZMemoryInspector()
12 | {
13 | dispatch_queue_t _lock;
14 | }
15 |
16 | @end
17 |
18 | @implementation VZMemoryInspector
19 |
20 |
21 | + (instancetype)sharedInstance
22 | {
23 | static VZMemoryInspector* instance;
24 | static dispatch_once_t onceToken;
25 | dispatch_once(&onceToken, ^{
26 | instance = [VZMemoryInspector new];
27 | });
28 | return instance;
29 | }
30 |
31 | static vm_size_t sPageSize = 0;
32 | static vm_statistics_data_t sVMStats;
33 |
34 |
35 | - (id)init
36 | {
37 | self = [super init];
38 |
39 | if (self)
40 | {
41 | _lock = dispatch_queue_create( "com.ETMemoryMonitor.taskQueue", nil );
42 |
43 | }
44 |
45 | return self;
46 | }
47 | - (void)dealloc
48 | {
49 | #if !OS_OBJECT_USE_OBJC
50 | dispatch_release(_lock);
51 | #endif
52 | }
53 |
54 |
55 | //for internal use
56 | + (BOOL)updateHostStatistics {
57 | mach_port_t host_port = mach_host_self();
58 | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
59 | host_page_size(host_port, &sPageSize);
60 | return (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&sVMStats, &host_size)
61 | == KERN_SUCCESS);
62 | }
63 | /*
64 | * The number of bytes in memory that used
65 | **/
66 |
67 | + (unsigned long long)bytesOfUsedMemory
68 | {
69 | /*
70 | * stackoverflow.com/questions/7989864/watching-memory-usage-in-ios
71 | */
72 | // struct task_basic_info info;
73 | // mach_msg_type_number_t size = sizeof(info);
74 | // kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
75 | // return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes
76 |
77 | struct mstats stat = mstats();
78 |
79 | return stat.bytes_used;
80 |
81 | }
82 |
83 | /**
84 | * The number of bytes in memory that are free.
85 | */
86 | + (unsigned long long)bytesOfFreeMemory
87 | {
88 | return NSRealMemoryAvailable();
89 | }
90 | /**
91 | * The total number of bytes of memory.
92 | */
93 | + (unsigned long long)bytesOfTotalMemory
94 | {
95 | [self updateHostStatistics];
96 |
97 | unsigned long long free_count = (unsigned long long)sVMStats.free_count;
98 | unsigned long long active_count = (unsigned long long)sVMStats.active_count;
99 | unsigned long long inactive_count = (unsigned long long)sVMStats.inactive_count;
100 | unsigned long long wire_count = (unsigned long long)sVMStats.wire_count;
101 | unsigned long long pageSize = (unsigned long long)sPageSize;
102 |
103 | unsigned long long mem_free = (free_count + active_count + inactive_count + wire_count) * pageSize;
104 |
105 |
106 | return mem_free;
107 | }
108 | + (void)performLowMemoryWarning
109 | {
110 | #ifdef DEBUG
111 | SEL memoryWarningSel = NSSelectorFromString(@"_performMemoryWarning");
112 | if ([[UIApplication sharedApplication] respondsToSelector:memoryWarningSel]) {
113 |
114 | #pragma clang diagnostic push
115 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
116 | [[UIApplication sharedApplication] performSelector:memoryWarningSel];
117 | #pragma clang diagnostic pop
118 |
119 | NSLog(@"[%@]-->memory warning",self.class);
120 |
121 | } else {
122 | // UIApplication no loger responds to _performMemoryWarning
123 | exit(1);
124 | }
125 | #endif
126 | }
127 |
128 | /**
129 | * The number of bytes free on disk.
130 | */
131 | + (unsigned long long)bytesOfFreeDiskSpace
132 | {
133 | return 0;
134 | }
135 | /**
136 | * The total number of bytes of disk space.
137 | */
138 | + (unsigned long long)bytesOfTotalDiskSpace
139 | {
140 | return 0;
141 | }
142 |
143 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////
144 | #pragma mark - for debugger use
145 |
146 | - (void)vz_heartBeat
147 | {
148 | if (self.samplePoints == nil)
149 | self.samplePoints = [NSMutableArray new];
150 |
151 | [self.samplePoints addObject:[NSNumber numberWithUnsignedLongLong:[[self class] bytesOfUsedMemory]]];
152 |
153 | //keep last 50 points
154 | if ( [self.samplePoints count] > 50 )
155 | {
156 | NSRange range;
157 | range.location = 0;
158 | range.length = [self.samplePoints count] - 50;
159 | [self.samplePoints removeObjectsInRange:range];
160 | }
161 | }
162 |
163 |
164 | @end
165 |
--------------------------------------------------------------------------------
/VZInspector/overview/memory/VZMemoryInspectorOverView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZMemoryInspectorOverView : UIView
8 |
9 | - (void)handleRead;
10 | - (void)handleWrite;
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/VZInspector/overview/memory/VZMemoryInspectorOverView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #include
6 | #import "VZMemoryInspectorOverView.h"
7 | #import "VZInspectorPlotView.h"
8 | #import "VZMemoryInspector.h"
9 | #import "NSObject+VZInspector.h"
10 |
11 |
12 | const int kThreshHold = 60.0f;
13 | @implementation VZMemoryInspectorOverView
14 | {
15 | UILabel * _titleView;
16 | UILabel * _statusView;
17 | VZInspectorPlotView* _plotView1;
18 | }
19 |
20 |
21 | - (id)initWithFrame:(CGRect)frame
22 | {
23 | self = [super initWithFrame:frame];
24 |
25 | if (self) {
26 | CGRect lineRect = CGRectMake(0, 0, frame.size.width, 1.0f);
27 |
28 | UIView *topLine = [[UIView alloc] initWithFrame:lineRect];
29 | topLine.backgroundColor = [UIColor colorWithWhite:0.5f alpha:1.0f];
30 | [self addSubview:topLine];
31 |
32 | UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectOffset(lineRect, 0, frame.size.height)];
33 | bottomLine.backgroundColor = [UIColor colorWithWhite:0.5f alpha:1.0f];
34 | [self addSubview:bottomLine];
35 |
36 | CGRect titleFrame;
37 | titleFrame.size.width = 90.0f;
38 | titleFrame.size.height = 20.0f;
39 | titleFrame.origin.x = 8.0f;
40 | titleFrame.origin.y = 0.0f;
41 |
42 | _titleView = [[UILabel alloc] initWithFrame:titleFrame];
43 | _titleView.textColor = [UIColor orangeColor];
44 | _titleView.textAlignment = NSTextAlignmentLeft;
45 | _titleView.font = [UIFont boldSystemFontOfSize:12.0f];
46 | _titleView.lineBreakMode = NSLineBreakByClipping;
47 | _titleView.backgroundColor = [UIColor clearColor];
48 | _titleView.numberOfLines = 1;
49 | _titleView.text = @"Memory Usage";
50 | [self addSubview:_titleView];
51 |
52 | CGRect statusFrame;
53 | statusFrame.size.width = 200;
54 | statusFrame.size.height = 20.0f;
55 | statusFrame.origin.x = frame.size.width - 200-10;
56 | statusFrame.origin.y = 0.0f;
57 |
58 | _statusView = [[UILabel alloc] initWithFrame:statusFrame];
59 | _statusView.textColor = [UIColor whiteColor];
60 | _statusView.textAlignment = NSTextAlignmentRight;
61 | _statusView.font = [UIFont boldSystemFontOfSize:12.0f];
62 | _statusView.lineBreakMode = NSLineBreakByClipping;
63 | _statusView.numberOfLines = 1;
64 | _statusView.backgroundColor = [UIColor clearColor];
65 | [self addSubview:_statusView];
66 |
67 | CGRect plotFrame;
68 | plotFrame.size.width = frame.size.width;
69 | plotFrame.size.height = frame.size.height - 20;
70 | plotFrame.origin.x = 0.0f;
71 | plotFrame.origin.y = 20.0f;
72 |
73 | _plotView1 = [[VZInspectorPlotView alloc] initWithFrame:plotFrame];
74 | _plotView1.alpha = 0.6f;
75 | _plotView1.lowerBound = 0.0f;
76 | _plotView1.upperBound = 0.0f;
77 | _plotView1.lineColor = [UIColor orangeColor];
78 | _plotView1.lineWidth = 2.0f;
79 | _plotView1.capacity = 50;
80 | _plotView1.fill = NO;
81 | [self addSubview:_plotView1];
82 | }
83 |
84 | return self;
85 | }
86 |
87 | - (void)dealloc
88 | {
89 | //NSLog(@"[%@]-->dealloc",self.class);
90 | }
91 |
92 | - (void)handleRead
93 | {
94 | [[VZMemoryInspector sharedInstance] vz_heartBeat];
95 | }
96 | - (void)handleWrite
97 | {
98 | [self writeHeartBeat];
99 | }
100 |
101 | - (void)writeHeartBeat
102 | {
103 | //NSLog(@"writeHeartBeat");
104 |
105 | float used = [VZMemoryInspector bytesOfUsedMemory];
106 | float total = [VZMemoryInspector bytesOfTotalMemory];
107 |
108 | float percent = (total > 0.0f) ? ((float)used / (float)total * 100.0f) : 0.0f;
109 | if ( percent >= kThreshHold )
110 | {
111 | //预警
112 | [UIView animateWithDuration:0.6f
113 | delay:0.0f
114 | options: UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
115 | animations: ^(void){self.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.6f];}
116 | completion:NULL];
117 | }
118 | else
119 | {
120 |
121 | [UIView animateWithDuration:0.6f
122 | delay:0.0f
123 | options: UIViewAnimationOptionBeginFromCurrentState
124 | animations: ^(void){self.backgroundColor = [UIColor clearColor];}
125 | completion:NULL];
126 | }
127 |
128 | NSMutableArray* tmp = [VZMemoryInspector sharedInstance].samplePoints;
129 | CGFloat _upperBound = 1;
130 | CGFloat _lowerBound = 0;
131 |
132 | for ( NSNumber * n in tmp )
133 | {
134 | if ( n.intValue > _upperBound )
135 | {
136 | _upperBound = n.intValue;
137 | if ( _upperBound < _lowerBound )
138 | {
139 | _lowerBound = _upperBound;
140 | }
141 | }
142 | else if ( n.intValue < _lowerBound )
143 | {
144 | _lowerBound = n.intValue;
145 | }
146 | }
147 |
148 |
149 | [_plotView1 setPlots:tmp];
150 | [_plotView1 setLowerBound:_lowerBound];
151 | [_plotView1 setUpperBound:_upperBound];
152 | [_plotView1 setNeedsDisplay];
153 |
154 |
155 |
156 | NSMutableString * text = [NSMutableString string];
157 | [text appendFormat:@"used:%@ (%.0f%%) ", [self number2String:used], percent];
158 | [text appendFormat:@"free:%@ ", [self number2String:total - used]];
159 | _statusView.text = text;
160 | }
161 |
162 | #define KB (1024)
163 | #define MB (KB * 1024)
164 | #define GB (MB * 1024)
165 |
166 | - (NSString* )number2String:(int64_t)n
167 | {
168 | if ( n < KB )
169 | {
170 | return [NSString stringWithFormat:@"%lldB", n];
171 | }
172 | else if ( n < MB )
173 | {
174 | return [NSString stringWithFormat:@"%.1fK", (float)n / (float)KB];
175 | }
176 | else if ( n < GB )
177 | {
178 | return [NSString stringWithFormat:@"%.1fM", (float)n / (float)MB];
179 | }
180 | else
181 | {
182 | return [NSString stringWithFormat:@"%.1fG", (float)n / (float)GB];
183 | }
184 | }
185 |
186 | @end
187 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/VZInspectorToolItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import
7 |
8 | @interface VZInspectorToolItem : NSObject
9 |
10 | @property (nonatomic, strong) NSString *name;
11 | @property (nonatomic, strong) UIImage *icon;
12 | @property (nonatomic, strong) NSString *status;
13 | @property (nonatomic, strong) NSString *(^callback)(NSString *status);
14 |
15 | + (instancetype)itemWithName:(NSString *)name icon:(UIImage *)icon callback:(void(^)(void))callback;
16 | + (instancetype)switchItemWithName:(NSString *)name icon:(UIImage *)icon callback:(BOOL(^)(BOOL on))callback;
17 | + (instancetype)statusItemWithName:(NSString *)name icon:(UIImage *)icon callback:(NSString *(^)(NSString *status))callback;
18 |
19 | - (void)performAction;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/VZInspectorToolItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorToolItem.h"
6 |
7 | @implementation VZInspectorToolItem
8 |
9 | + (instancetype)statusItemWithName:(NSString *)name icon:(UIImage *)icon callback:(NSString *(^)(NSString *status))callback {
10 | VZInspectorToolItem *item = [VZInspectorToolItem new];
11 | item.name = name;
12 | item.icon = icon;
13 | item.callback = callback;
14 | return item;
15 | }
16 |
17 | + (instancetype)itemWithName:(NSString *)name icon:(UIImage *)icon callback:(void (^)(void))callback {
18 | return [self statusItemWithName:name icon:icon callback:^NSString *(NSString *status) {
19 | callback();
20 | return status;
21 | }];
22 | }
23 |
24 | + (instancetype)switchItemWithName:(NSString *)name icon:(UIImage *)icon callback:(BOOL (^)(BOOL on))callback {
25 | return [self statusItemWithName:name icon:icon callback:^(NSString *status) {
26 | return callback(!!status) ? @"ON" : nil;
27 | }];
28 | }
29 |
30 |
31 |
32 | - (void)performAction {
33 | if (self.callback) {
34 | self.status = self.callback(self.status);
35 | }
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/VZInspectorToolboxView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 | #import "VZInspectorToolItem.h"
7 |
8 | @interface VZInspectorToolboxView : VZInspectorView
9 |
10 | - (void)addToolItem:(VZInspectorToolItem *)toolItem;
11 | - (void)setIcon:(UIImage *)icon;
12 |
13 | - (void)updateCollectionView;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/VZInspectorToolboxView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | #import "VZInspectorToolboxView.h"
8 | #import "VZInspectorResource.h"
9 | #import "VZDefine.h"
10 |
11 | #define kVZInspectorToolItemCellReuseId @"kVZInspectorToolItemCellReuseId"
12 |
13 |
14 | @interface VZInspectorToolItemCell : UICollectionViewCell
15 |
16 | @property (nonatomic, strong) VZInspectorToolItem *item;
17 |
18 | @end
19 |
20 | @implementation VZInspectorToolItemCell
21 | {
22 | UIImageView *_iconView;
23 | UILabel *_nameLabel;
24 | UILabel *_statusLabel;
25 | UIView *_statusView;
26 | }
27 |
28 | - (void)setItem:(VZInspectorToolItem *)item {
29 | _item = item;
30 | _iconView.image = item.icon;
31 | _nameLabel.text = item.name;
32 | _statusView.hidden = !item.status;
33 | _statusLabel.text = item.status;
34 | }
35 |
36 | - (instancetype)initWithFrame:(CGRect)frame {
37 | if (self = [super initWithFrame:frame]) {
38 | self.contentView.clipsToBounds = YES;
39 | self.layer.borderWidth = kOnePix;
40 | self.layer.borderColor = VZ_INSPECTOR_MAIN_COLOR.CGColor;
41 |
42 | const CGFloat textHeight = 15;
43 | const CGFloat imageSize = 32;
44 | const CGFloat spacing = 3;
45 | const CGFloat totalHeight = textHeight + spacing + imageSize;
46 |
47 | _iconView = [[UIImageView alloc] initWithFrame:CGRectMake((frame.size.width - imageSize) / 2, (frame.size.height - totalHeight) / 2, imageSize, imageSize)];
48 | _iconView.contentMode = UIViewContentModeScaleAspectFit;
49 | [self.contentView addSubview:_iconView];
50 |
51 | _nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, _iconView.frame.origin.y + imageSize + spacing, frame.size.width, textHeight)];
52 | _nameLabel.font = [UIFont systemFontOfSize:12.0];
53 | _nameLabel.textColor = VZ_INSPECTOR_MAIN_COLOR;
54 | _nameLabel.textAlignment = NSTextAlignmentCenter;
55 | [self.contentView addSubview:_nameLabel];
56 |
57 | CGFloat w = frame.size.width;
58 | _statusView = [[UIView alloc] init];
59 | _statusView.layer.anchorPoint = CGPointMake(1, 1);
60 | _statusView.frame = CGRectMake(w - w * M_SQRT2 / 2, w / 2 - w * M_SQRT2 / 8, w * M_SQRT2 / 2, w * M_SQRT2 / 8);
61 | _statusView.transform = CGAffineTransformMakeRotation(M_PI_4);
62 | _statusView.backgroundColor = VZ_INSPECTOR_MAIN_COLOR;
63 |
64 | _statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(w * M_SQRT2 / 8, 0, w * M_SQRT2 / 4, w * M_SQRT2 / 8)];
65 | _statusLabel.textColor = [UIColor whiteColor];
66 | _statusLabel.textAlignment = NSTextAlignmentCenter;
67 | _statusLabel.font = [UIFont systemFontOfSize:10];
68 | _statusLabel.adjustsFontSizeToFitWidth = YES;
69 | _statusLabel.minimumScaleFactor = 0.7;
70 | [_statusView addSubview:_statusLabel];
71 | [self.contentView addSubview:_statusView];
72 | }
73 | return self;
74 | }
75 |
76 | @end
77 |
78 |
79 | @interface VZInspectorToolboxView()
80 |
81 | @property (nonatomic, strong) NSMutableArray *tools;
82 |
83 | @end
84 |
85 |
86 | @implementation VZInspectorToolboxView
87 | {
88 | UICollectionView *_collectionView;
89 | UIImageView *_logoView;
90 | UIView *_emptyView;
91 | }
92 |
93 | - (id)initWithFrame:(CGRect)frame
94 | {
95 | self = [super initWithFrame:frame];
96 | if (self) {
97 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
98 | flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
99 | flowLayout.minimumInteritemSpacing = 0;
100 | flowLayout.minimumLineSpacing = 0;
101 | flowLayout.itemSize = CGSizeMake(frame.size.width / 5, frame.size.width / 5);
102 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 120, frame.size.width, frame.size.height - 120) collectionViewLayout:flowLayout];
103 | _collectionView.dataSource = self;
104 | _collectionView.delegate = self;
105 | _collectionView.bounces = YES;
106 | _collectionView.showsHorizontalScrollIndicator = NO;
107 | _collectionView.showsVerticalScrollIndicator = NO;
108 | _collectionView.backgroundColor = [UIColor clearColor];
109 | [_collectionView registerClass:[VZInspectorToolItemCell class] forCellWithReuseIdentifier:kVZInspectorToolItemCellReuseId];
110 | [self addSubview:_collectionView];
111 |
112 | _logoView = [[UIImageView alloc]initWithFrame:CGRectMake((frame.size.width - 60)/2, 30, 60, 60)];
113 | _logoView.image = [VZInspectorResource logo];
114 | _logoView.contentMode = UIViewContentModeScaleAspectFit;
115 | [self addSubview:_logoView];
116 |
117 | UIView* line = [[UIView alloc] initWithFrame:CGRectMake(0, _collectionView.frame.origin.y, frame.size.width, 1)];
118 | line.backgroundColor = VZ_INSPECTOR_MAIN_COLOR;
119 | [self addSubview:line];
120 |
121 | UILabel *label = [[UILabel alloc] initWithFrame:_collectionView.frame];
122 | label.text = @"No Plugins";
123 | label.textColor = VZ_INSPECTOR_MAIN_COLOR;
124 | label.font = [UIFont systemFontOfSize:24];
125 | label.textAlignment = NSTextAlignmentCenter;
126 | [self addSubview:label];
127 | _emptyView = label;
128 | }
129 |
130 | return self;
131 | }
132 |
133 | - (void)dealloc {
134 | _collectionView.delegate = nil;
135 | _collectionView.dataSource = nil;
136 | }
137 |
138 | - (void)setIcon:(UIImage *)icon {
139 | _logoView.image = icon;
140 | }
141 |
142 | - (NSMutableArray *)tools {
143 | if (!_tools) {
144 | _tools = [NSMutableArray array];
145 | }
146 | return _tools;
147 | }
148 |
149 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
150 | {
151 | return self.tools.count;
152 | }
153 |
154 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
155 | {
156 | VZInspectorToolItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kVZInspectorToolItemCellReuseId forIndexPath:indexPath];
157 | cell.item = self.tools[indexPath.item];
158 | return cell;
159 | }
160 |
161 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
162 | VZInspectorToolItem *item = self.tools[indexPath.item];
163 | [item performAction];
164 | [_collectionView reloadItemsAtIndexPaths:@[indexPath]];
165 | }
166 |
167 | - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
168 | UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
169 | cell.backgroundColor = [VZ_INSPECTOR_MAIN_COLOR colorWithAlphaComponent:0.3];
170 | }
171 |
172 | - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
173 | UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
174 | cell.backgroundColor = [UIColor clearColor];
175 | }
176 |
177 | - (void)addToolItem:(VZInspectorToolItem *)toolItem {
178 | [self.tools addObject:toolItem];
179 | _emptyView.hidden = YES;
180 | }
181 |
182 | - (void)updateCollectionView{
183 | if(_collectionView){
184 | [_collectionView reloadData];
185 | }
186 | }
187 |
188 | @end
189 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/border/VZBorderInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZBorderInspector : NSObject
8 |
9 | @property(nonatomic,assign,readonly) BOOL isON;
10 |
11 | + (instancetype)sharedInstance;
12 | + (void)setViewClassPrefixName:(NSString* )name;
13 |
14 | - (void)showBorder;
15 | - (void)showViewClassName;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/border/VZBorderInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZBorderInspector.h"
6 | #import "VZInspectorTimer.h"
7 | #import
8 | #import
9 |
10 | @interface UIView(VZBorderLayerTag)
11 |
12 | @property(nonatomic,strong) NSNumber* layerTag;
13 |
14 | @end
15 |
16 | @implementation UIView(VZBorderLayerTag)
17 |
18 | - (void)setLayerTag:(NSNumber *)layerTag
19 | {
20 | objc_setAssociatedObject(self, "VZBorderLayerTag", layerTag, OBJC_ASSOCIATION_RETAIN);
21 | }
22 |
23 | - (NSNumber* )layerTag
24 | {
25 | return objc_getAssociatedObject(self, "VZBorderLayerTag");
26 | }
27 |
28 | - (UIView* )viewWithLayerTag:(NSNumber* )layerTag
29 | {
30 | UIView* v = nil;
31 |
32 | for (UIView* subview in self.subviews)
33 | {
34 | if ([v.layerTag integerValue] == [layerTag integerValue]) {
35 | v = subview;
36 | break;
37 | }
38 | }
39 |
40 | return v;
41 | }
42 |
43 | @end
44 |
45 |
46 | @interface NSTimer(VZBorderInspector)
47 | +(NSTimer* )scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void(^)(void))block userInfo:(id)userInfo repeats:(BOOL)repeat;
48 | @end
49 |
50 | @implementation NSTimer(VZBorderInspector)
51 |
52 | + (NSTimer* )scheduledTimerWithTimeInterval:(NSTimeInterval)ti block:(void (^)(void))block userInfo:(id)userInfo repeats:(BOOL)repeat
53 | {
54 | return [NSTimer scheduledTimerWithTimeInterval:ti target:self selector:@selector(onTimerFired:) userInfo:[block copy] repeats:repeat];
55 | }
56 |
57 | + (void)onTimerFired:(NSTimer* )timer
58 | {
59 | void(^block)(void) = timer.userInfo;
60 |
61 | if (block) {
62 | block();
63 | }
64 | }
65 |
66 | @end
67 |
68 | #define kVZBorderLayerTag 729
69 |
70 | @interface VZBorderItem:NSObject
71 |
72 | @property(nonatomic,weak) UIView* view;
73 | @property(nonatomic,assign) CGFloat borderWidth;
74 | @property(nonatomic,strong) UIColor* borderColor;
75 |
76 |
77 | @end
78 |
79 | @implementation VZBorderItem
80 | @end
81 |
82 | @interface VZBorderInspector ()
83 | {
84 | BOOL _on;
85 | NSMutableSet* _set;
86 | }
87 |
88 | @property(nonatomic,strong) NSTimer* timer;
89 | @property(nonatomic,strong) NSString* prefixName;
90 | @property(nonatomic,assign) float borderWidth;
91 |
92 |
93 | @end
94 |
95 | @implementation VZBorderInspector
96 |
97 | + (instancetype)sharedInstance {
98 | static VZBorderInspector *instance;
99 | static dispatch_once_t onceToken;
100 | dispatch_once(&onceToken, ^{
101 | if (!instance) {
102 | instance = [VZBorderInspector new];
103 | }
104 | });
105 |
106 | return instance;
107 | }
108 |
109 | + (void)setViewClassPrefixName:(NSString* )name
110 | {
111 | [[self sharedInstance] setPrefixName:name];
112 | }
113 |
114 | - (BOOL)isON
115 | {
116 | return _on;
117 | }
118 |
119 | - (id)init
120 | {
121 | self = [super init];
122 |
123 | if (self) {
124 |
125 | _borderWidth = 0.5;
126 | _set = [NSMutableSet new];
127 |
128 | }
129 | return self;
130 | }
131 |
132 | - (void)dealloc
133 | {
134 | [[NSNotificationCenter defaultCenter] removeObserver:self];
135 | }
136 |
137 | - (void)showBorder
138 | {
139 | _on = !_on;
140 |
141 | if (_on) {
142 |
143 | __weak typeof(self) weakSelf = self;
144 | self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5 block:^{
145 |
146 | [weakSelf timerTriggered];
147 |
148 | } userInfo:nil repeats:YES];
149 | }
150 | else
151 | {
152 | [self.timer invalidate];
153 | self.timer = nil;
154 | [self timerStopped];
155 | }
156 | }
157 |
158 | - (void)showViewClassName
159 | {
160 | //todo...
161 | }
162 |
163 | - (void)timerTriggered
164 | {
165 | if (_on)
166 | {
167 | [self recoverViewBorder];
168 | [_set removeAllObjects];
169 | [self updateBorderOfViewHierarchy];
170 | }
171 | }
172 |
173 | - (void)timerStopped
174 | {
175 | if (!_on)
176 | {
177 | [self recoverViewBorder];
178 | [_set removeAllObjects];
179 | }
180 | }
181 |
182 |
183 |
184 | - (void)updateBorderOfViewHierarchy {
185 |
186 | UIViewController *currentVC = nil;
187 | UIWindow * window = [[UIApplication sharedApplication] keyWindow];
188 | UIView *frontView = [[window subviews] objectAtIndex:0];
189 | id nextResponder = [frontView nextResponder];
190 |
191 | if ([nextResponder isKindOfClass:[UIViewController class]])
192 | currentVC = nextResponder;
193 | else
194 | currentVC = window.rootViewController;
195 |
196 | [self drawBorderOfViewHierarchy:currentVC.view];
197 | }
198 |
199 | - (void)drawBorderOfViewHierarchy:(UIView *)view {
200 |
201 | //all border
202 | VZBorderItem* item = [VZBorderItem new];
203 | item.borderColor = [UIColor colorWithCGColor:view.layer.borderColor];
204 | item.borderWidth = view.layer.borderWidth;
205 | item.view = view;
206 | [_set addObject:item];
207 |
208 | view.layer.borderWidth = self.borderWidth;
209 | view.layer.borderColor = [UIColor orangeColor].CGColor;
210 |
211 | NSString* className = NSStringFromClass([view class]);
212 |
213 | if (self.prefixName.length > 0 )
214 | {
215 |
216 | if ([className hasPrefix:self.prefixName]) {
217 |
218 | if ([view viewWithTag:kVZBorderLayerTag]) {
219 |
220 | UILabel* label = (UILabel* )[view viewWithTag:kVZBorderLayerTag];
221 | label.text = className;
222 | }
223 | else
224 | {
225 | UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, view.bounds.size.width, 12)];
226 | label.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5];
227 | label.textAlignment = NSTextAlignmentLeft;
228 | label.text = className;
229 | label.textColor = [UIColor cyanColor];
230 | label.font = [UIFont systemFontOfSize:9.0];
231 | label.tag = kVZBorderLayerTag;
232 | //label.layerTag = @(kVZBorderLayerTag);
233 | [view addSubview:label];
234 | }
235 |
236 | }
237 | }
238 | for (UIView* subview in view.subviews)
239 | {
240 | if (subview.tag == kVZBorderLayerTag) {
241 | continue;
242 | }
243 | [self drawBorderOfViewHierarchy:subview];
244 | }
245 | }
246 |
247 | - (void)recoverViewBorder
248 | {
249 | [_set enumerateObjectsUsingBlock:^(VZBorderItem* obj, BOOL *stop) {
250 |
251 | if (obj.view)
252 | {
253 | [[obj.view viewWithTag:kVZBorderLayerTag] removeFromSuperview];
254 | obj.view.layer.borderWidth = obj.borderWidth;
255 | obj.view.layer.borderColor = obj.borderColor.CGColor;
256 | }
257 | }];
258 | }
259 |
260 |
261 |
262 |
263 |
264 | @end
265 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/colorPicker/VZColorDisplayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @class VZColorDisplayView;
8 |
9 | @protocol VZColorDisplayViewDelegate
10 |
11 | - (void)displayView:(VZColorDisplayView *)displayView colorDidUpdate:(UIColor *)color;
12 |
13 | @end
14 |
15 | //宽高要设置成奇数
16 | @interface VZColorDisplayView : UIView
17 |
18 | + (instancetype)displayViewWithRadius:(CGFloat)r scale:(NSUInteger)scale;
19 |
20 |
21 | @property (nonatomic, assign) NSUInteger scale; //放大倍数,>=1
22 | @property (nonatomic, weak) id delegate;
23 |
24 | - (void)update;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/colorPicker/VZColorPanelView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @class VZColorPanelView;
8 |
9 | @protocol VZColorPanelViewDelegate
10 |
11 | - (void)panelView:(VZColorPanelView *)panelView ratioDidChange:(NSInteger )ratio;
12 |
13 | @end
14 |
15 | @interface VZColorPanelView : UIView
16 |
17 | @property (nonatomic, weak) id delegate;
18 |
19 | - (void)updateColor:(UIColor *)color;
20 |
21 | - (id)initWithFrame:(CGRect)frame defaultRatio:(NSInteger)defaultRatio;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/colorPicker/VZColorPickerDefine.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #ifndef VZColorPickerDefine_h
6 | #define VZColorPickerDefine_h
7 |
8 | static const NSUInteger kVZCPMinZoomValue = 5;
9 | static const NSUInteger kVZCPMaxZoomValue = 30;
10 |
11 |
12 | #endif /* VZColorPickerDefine_h */
13 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/colorPicker/VZInspectorColorPickerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorColorPickerView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/colorPicker/VZInspectorColorPickerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorColorPickerView.h"
6 | #import "VZColorDisplayView.h"
7 | #import "VZColorPanelView.h"
8 |
9 | @interface VZInspectorColorPickerView()
10 |
11 | @property(nonatomic,strong)UIButton* backBtn;
12 | @property(nonatomic,strong)VZColorDisplayView *colorDisplayView;
13 | @property(nonatomic,strong)VZColorPanelView *colorPanelView;
14 |
15 | @property(nonatomic,assign) CGPoint fromPoint;
16 | @property(nonatomic,assign) CGPoint touchFromPoint;
17 | @property(nonatomic,assign) BOOL isMoving;
18 | @property(nonatomic,assign) BOOL isFromCircle;//是否从圆圈开始拖动
19 | @end
20 |
21 |
22 | @implementation VZInspectorColorPickerView
23 |
24 | /*
25 | // Only override drawRect: if you perform custom drawing.
26 | // An empty implementation adversely affects performance during animation.
27 | - (void)drawRect:(CGRect)rect {
28 | // Drawing code
29 | }
30 | */
31 |
32 | - (id)initWithFrame:(CGRect)frame parentViewController:(UIViewController *)controller {
33 | self = [super initWithFrame:frame parentViewController:controller];
34 | if (self) {
35 | self.backgroundColor = [UIColor clearColor];
36 |
37 | self.backBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 44, 44)];
38 | self.backBtn.backgroundColor = [UIColor clearColor];
39 | [self.backBtn setTitle:@"<-" forState:UIControlStateNormal];
40 | [self.backBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
41 | self.backBtn.titleLabel.font = [UIFont systemFontOfSize:18.0f];
42 | #pragma clang diagnostic push
43 | #pragma clang diagnostic ignored "-Wundeclared-selector"
44 | [self.backBtn addTarget:self.parentViewController action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
45 | #pragma clang diagnostic pop
46 | [self addSubview:self.backBtn];
47 |
48 | NSUInteger defaultScale = 5;
49 |
50 | self.colorDisplayView = [VZColorDisplayView displayViewWithRadius:101 scale:defaultScale];
51 | self.colorDisplayView.center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
52 | self.colorDisplayView.delegate = self;
53 | [self addSubview:self.colorDisplayView];
54 |
55 | [self.colorDisplayView update];
56 |
57 |
58 | self.colorPanelView = [[VZColorPanelView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - 150, self.frame.size.width, 150) defaultRatio:defaultScale];
59 | self.colorPanelView.delegate = self;
60 | [self.colorPanelView updateColor:[UIColor colorWithWhite:0.3 alpha:0.2]];
61 | [self addSubview:self.colorPanelView];
62 |
63 | self.multipleTouchEnabled = NO;
64 | }
65 | return self;
66 | }
67 |
68 | - (void)displayView:(VZColorDisplayView *)displayView colorDidUpdate:(UIColor *)color {
69 | [self.colorPanelView updateColor:color];
70 | }
71 |
72 | - (void)panelView:(VZColorPanelView *)panelView ratioDidChange:(NSInteger )ratio {
73 | if (ratio <= 1) {
74 | ratio = 1;
75 | }
76 | [self.colorDisplayView setScale:ratio];
77 | }
78 |
79 | - (BOOL)isTouchInDisplayView:(UITouch *)touch {
80 | CGPoint touchPoint = [touch locationInView:self];
81 | return CGRectContainsPoint(self.colorDisplayView.frame, touchPoint);
82 | }
83 |
84 | - (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event {
85 |
86 | do {
87 | if ([touches count] != 1) {
88 | break;
89 | }
90 |
91 | UITouch *touch = [touches anyObject];
92 |
93 | self.isFromCircle = [self isTouchInDisplayView:touch];
94 |
95 | self.isMoving = YES;
96 | self.fromPoint = self.colorDisplayView.frame.origin;
97 | self.touchFromPoint = [touch locationInView:self];
98 | return;
99 | } while (0);
100 |
101 |
102 | [super touchesBegan:touches withEvent:event];
103 |
104 |
105 | }
106 |
107 | - (void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event {
108 | if (!self.isMoving) {
109 | return [super touchesMoved:touches withEvent:event];
110 | }
111 |
112 | UITouch *touch = [touches anyObject];
113 |
114 | CGPoint touchPoint = [touch locationInView:self];
115 |
116 | CGRect frame = self.colorDisplayView.frame;
117 |
118 | CGFloat rate = self.isFromCircle ? 1 : 0.03;
119 |
120 | //整像素点
121 | frame.origin.x = rate * (touchPoint.x - self.touchFromPoint.x) + self.fromPoint.x;
122 | frame.origin.y = rate * (touchPoint.y - self.touchFromPoint.y) + self.fromPoint.y;
123 |
124 | [self updateColorDisplayViewFrame:frame];
125 | }
126 |
127 | - (void)updateColorDisplayViewFrame:(CGRect)frame {
128 |
129 | CGFloat scale = [[UIScreen mainScreen] scale];
130 |
131 | //四舍五入
132 | frame.origin.x = floor((frame.origin.x) * scale + 0.5) / scale;
133 | frame.origin.y = floor((frame.origin.y) * scale + 0.5) / scale;
134 |
135 | if (frame.origin.x < self.bounds.origin.x - frame.size.width * 0.5) {
136 | frame.origin.x = self.bounds.origin.x - frame.size.width * 0.5;
137 | }
138 |
139 | if (frame.origin.x > self.bounds.origin.x + self.bounds.size.width - frame.size.width * 0.5) {
140 | frame.origin.x = self.bounds.origin.x + self.bounds.size.width - frame.size.width * 0.5;
141 | }
142 |
143 | if (frame.origin.y < self.bounds.origin.y - frame.size.height * 0.5) {
144 | frame.origin.y = self.bounds.origin.y - frame.size.height * 0.5;
145 | }
146 |
147 | if (frame.origin.y > self.bounds.origin.y + self.bounds.size.height - frame.size.height * 0.5) {
148 | frame.origin.y = self.bounds.origin.y + self.bounds.size.height - frame.size.height * 0.5;
149 | }
150 |
151 | if (frame.origin.x != self.colorDisplayView.frame.origin.x
152 | || frame.origin.y != self.colorDisplayView.frame.origin.y) {
153 | //防止频繁刷新
154 | self.colorDisplayView.frame = frame;
155 |
156 | [self.colorDisplayView update];
157 | }
158 |
159 |
160 | CGRect panelDownFrame = self.colorPanelView.frame; //在下边时候的frame
161 | panelDownFrame.origin.y = self.frame.size.height - self.colorPanelView.frame.size.height;
162 |
163 | if (CGRectIntersectsRect(self.colorDisplayView.frame, panelDownFrame)) {
164 | CGRect frame = self.colorPanelView.frame;
165 | frame.origin.y = 0;
166 | self.colorPanelView.frame = frame;
167 |
168 | frame = self.backBtn.frame;
169 | frame.origin.y = self.colorPanelView.frame.origin.y + self.colorPanelView.frame.size.height + 10;
170 | self.backBtn.frame = frame;
171 | } else {
172 | self.colorPanelView.frame = panelDownFrame;
173 |
174 | CGRect frame = self.backBtn.frame;
175 | frame.origin.y = 0;
176 | self.backBtn.frame = frame;
177 | }
178 | }
179 |
180 |
181 | - (void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event {
182 | if (!_isMoving) {
183 | [super touchesEnded:touches withEvent:event];
184 | }
185 | self.isMoving = NO;
186 | }
187 | - (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *) event {
188 | if (!self.isMoving) {
189 | [super touchesCancelled:touches withEvent:event];
190 | }
191 | self.isMoving = NO;
192 | }
193 |
194 | @end
195 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZCrashInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZCrashInspector : NSObject
8 |
9 | + (instancetype)sharedInstance;
10 | - (void)install;
11 | - (NSDictionary* )crashForKey:(NSString* )key;
12 | - (NSArray* )crashPlist;
13 | - (NSArray* )crashLogs;
14 |
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZCrashInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZCrashInspector.h"
6 | #include
7 | #include
8 |
9 | @implementation VZCrashInspector
10 |
11 | {
12 | BOOL _isInstalled;
13 | NSString* _crashLogPath;
14 | NSMutableArray* _plist;
15 | }
16 |
17 | + (instancetype)sharedInstance
18 | {
19 | static VZCrashInspector* instance;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | instance = [VZCrashInspector new];
23 | });
24 | return instance;
25 | }
26 |
27 | const int maxCrashLogNum = 20;
28 |
29 | //handle exception
30 |
31 | void vz_HandleException(NSException *exception)
32 | {
33 | [[VZCrashInspector sharedInstance]saveException:exception];
34 | [exception raise];
35 | }
36 |
37 | void vz_SignalHandler(int sig)
38 | {
39 | [[VZCrashInspector sharedInstance]saveSignal:sig];
40 |
41 | signal(sig, SIG_DFL);
42 | raise(sig);
43 | }
44 |
45 | + (NSArray *)backtrace
46 | {
47 | void* callstack[128];
48 | int frames = backtrace(callstack, 128);
49 | char **strs = backtrace_symbols(callstack, frames);
50 |
51 | NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
52 |
53 | for (int i = 0;i < 32;i++)
54 | {
55 | [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
56 | }
57 | free(strs);
58 |
59 | return backtrace;
60 | }
61 |
62 | - (id)init
63 | {
64 | self = [super init];
65 | if ( self )
66 | {
67 | NSArray * paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
68 | NSString* sandBoxPath = [paths objectAtIndex:0];
69 |
70 |
71 | _crashLogPath = [sandBoxPath stringByAppendingPathComponent:@"VZCrashLog"];
72 |
73 | if ( NO == [[NSFileManager defaultManager] fileExistsAtPath:_crashLogPath] )
74 | {
75 | [[NSFileManager defaultManager] createDirectoryAtPath:_crashLogPath
76 | withIntermediateDirectories:YES
77 | attributes:nil
78 | error:NULL];
79 | }
80 |
81 | //creat plist
82 | if (YES == [[NSFileManager defaultManager] fileExistsAtPath:[_crashLogPath stringByAppendingPathComponent:@"crashLog.plist"]])
83 | {
84 | _plist = [[NSMutableArray arrayWithContentsOfFile:[_crashLogPath stringByAppendingPathComponent:@"crashLog.plist"]] mutableCopy];
85 | }
86 | else
87 | _plist = [NSMutableArray new];
88 | }
89 | return self;
90 | }
91 |
92 | - (NSDictionary* )crashForKey:(NSString *)key
93 | {
94 | NSString* filePath = [[_crashLogPath stringByAppendingPathComponent:key] stringByAppendingString:@".plist"];
95 | NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
96 |
97 | return dict;
98 | }
99 |
100 | - (NSArray* )crashPlist
101 | {
102 | return [_plist copy];
103 | }
104 |
105 | - (NSArray* )crashLogs
106 | {
107 | NSMutableArray* ret = [NSMutableArray new];
108 | for (NSString* key in _plist) {
109 |
110 | NSString* filePath = [_crashLogPath stringByAppendingPathComponent:key];
111 | NSString* path = [filePath stringByAppendingString:@".plist"];
112 | NSDictionary* log = [NSDictionary dictionaryWithContentsOfFile:path];
113 | [ret addObject:log];
114 | }
115 | return [ret copy];
116 | }
117 |
118 |
119 | - (NSDictionary* )crashReport
120 | {
121 | for (NSString* key in _plist) {
122 |
123 | NSString* filePath = [_crashLogPath stringByAppendingPathComponent:key];
124 |
125 | NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
126 |
127 | return dict;
128 | }
129 | return nil;
130 |
131 | }
132 |
133 | - (void)install
134 | {
135 | if (_isInstalled) {
136 | return;
137 | }
138 | //注册回调函数
139 | NSSetUncaughtExceptionHandler(&vz_HandleException);
140 | signal(SIGABRT, vz_SignalHandler);
141 | signal(SIGILL, vz_SignalHandler);
142 | signal(SIGSEGV, vz_SignalHandler);
143 | signal(SIGFPE, vz_SignalHandler);
144 | signal(SIGBUS, vz_SignalHandler);
145 | signal(SIGPIPE, vz_SignalHandler);
146 | }
147 |
148 | - (void)dealloc
149 | {
150 | signal( SIGABRT, SIG_DFL );
151 | signal( SIGBUS, SIG_DFL );
152 | signal( SIGFPE, SIG_DFL );
153 | signal( SIGILL, SIG_DFL );
154 | signal( SIGPIPE, SIG_DFL );
155 | signal( SIGSEGV, SIG_DFL );
156 | }
157 |
158 | - (void)saveException:(NSException*)exception
159 | {
160 | NSMutableDictionary * detail = [NSMutableDictionary dictionary];
161 | if ( exception.name )
162 | {
163 | [detail setObject:exception.name forKey:@"name"];
164 | }
165 | if ( exception.reason )
166 | {
167 | [detail setObject:exception.reason forKey:@"reason"];
168 | }
169 | if ( exception.userInfo )
170 | {
171 | [detail setObject:exception.userInfo forKey:@"userInfo"];
172 | }
173 | if ( exception.callStackSymbols )
174 | {
175 | [detail setObject:exception.callStackSymbols forKey:@"callStack"];
176 | }
177 |
178 | NSMutableDictionary * dict = [NSMutableDictionary dictionary];
179 | [dict setObject:@"exception" forKey:@"type"];
180 | [dict setObject:detail forKey:@"info"];
181 |
182 | [self saveToFile:dict];
183 |
184 | }
185 |
186 | - (void)saveSignal:(int) signal
187 | {
188 | // NSMutableDictionary * detail = [NSMutableDictionary dictionary];
189 | //
190 | // [detail setObject:@(signal) forKey:@"signal type"];
191 |
192 | // [self saveToFile:detail];
193 | }
194 |
195 | - (void)saveToFile:(NSMutableDictionary*)dict
196 | {
197 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
198 | [formatter setDateFormat:@"yyyyMMdd_HHmmss"];
199 | NSString* dateString = [formatter stringFromDate:[NSDate date]];
200 |
201 | //add date
202 | [dict setObject:dateString forKey:@"date"];
203 |
204 | //save path
205 | NSString* savePath = [[_crashLogPath stringByAppendingPathComponent:dateString] stringByAppendingString:@".plist"];
206 |
207 | //save to disk
208 | BOOL succeed = [ dict writeToFile:savePath atomically:YES];
209 | if ( NO == succeed )
210 | {
211 | NSLog(@"VZInspector:Save crash report failed!");
212 | }
213 | else
214 | NSLog(@"VZInspector:save crash report succeed!");
215 |
216 | [_plist insertObject:dateString atIndex:0];
217 | // [_plist writeToFile:[_crashLogPath stringByAppendingPathComponent:@"crashLog.plist"] atomically:YES];
218 |
219 | if (_plist.count > maxCrashLogNum)
220 | {
221 | [[NSFileManager defaultManager] removeItemAtPath:[_crashLogPath stringByAppendingPathComponent:_plist[0]] error:nil];
222 | [_plist removeObjectAtIndex:0];
223 |
224 | }
225 | [_plist writeToFile:[_crashLogPath stringByAppendingPathComponent:@"crashLog.plist"] atomically:YES];
226 | }
227 |
228 | @end
229 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZInspectorCrashRootView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZInspectorView.h"
7 |
8 | @interface VZInspectorCrashRootView : VZInspectorView
9 |
10 | @end
11 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZInspectorCrashRootView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorCrashRootView.h"
6 | #import "VZInspectorCrashView.h"
7 | #import "VZCrashInspector.h"
8 |
9 |
10 | @interface VZInspectorCrashRootHeaderView : UIView
11 |
12 | @property(nonatomic,strong) UILabel* textLabel;
13 | @property(nonatomic,strong) UIButton* backBtn;
14 | @property(nonatomic,weak) id delegate;
15 |
16 | @end
17 |
18 | @implementation VZInspectorCrashRootHeaderView
19 |
20 | - (id)initWithFrame:(CGRect)frame
21 | {
22 | self = [super initWithFrame:frame];
23 |
24 | if (self) {
25 |
26 | self.textLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 13, frame.size.width, 18)];
27 | self.textLabel.textAlignment = NSTextAlignmentCenter;
28 | self.textLabel.textColor = [UIColor whiteColor];
29 | self.textLabel.backgroundColor = [UIColor clearColor];
30 | self.textLabel.font = [UIFont systemFontOfSize:18.0f];
31 | [self addSubview:self.textLabel];
32 |
33 | self.backBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 44, 44)];
34 | self.backBtn.backgroundColor = [UIColor clearColor];
35 | [self.backBtn setTitle:@"<-" forState:UIControlStateNormal];
36 | [self.backBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
37 | self.backBtn.titleLabel.font = [UIFont systemFontOfSize:18.0f];
38 | #pragma clang diagnostic push
39 | #pragma clang diagnostic ignored "-Wundeclared-selector"
40 | [self.backBtn addTarget:self.delegate action:@selector(pop) forControlEvents:UIControlEventTouchUpInside];
41 | #pragma clang diagnostic pop
42 | [self addSubview:self.backBtn];
43 | }
44 | return self;
45 | }
46 |
47 | @end
48 |
49 | @interface VZInspectorCrashRootView()
50 |
51 | @property(nonatomic,strong)VZInspectorCrashRootHeaderView* headerView;
52 | @property(nonatomic,strong)NSString* filename;
53 | @property(nonatomic,strong)UIView* contentView;
54 | @property(nonatomic,strong)UITableView* listView;
55 | @property(nonatomic,strong)VZInspectorCrashView* subView;
56 | @property(nonatomic,strong)NSArray* pathNames;
57 |
58 |
59 | @end
60 |
61 | @implementation VZInspectorCrashRootView
62 |
63 | - (id)initWithFrame:(CGRect)frame parentViewController:(UIViewController *)controller
64 | {
65 | self = [super initWithFrame:frame parentViewController:controller];
66 |
67 | if (self) {
68 |
69 |
70 | //contentview
71 | self.contentView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
72 | self.contentView.backgroundColor = [UIColor clearColor];
73 | [self addSubview:self.contentView];
74 |
75 |
76 | //header view
77 | self.headerView = [[VZInspectorCrashRootHeaderView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, 44)];
78 | self.headerView.delegate = self;
79 | self.headerView.textLabel.text = @"All Crashes";
80 | [self.contentView addSubview:self.headerView];
81 |
82 | //list view
83 | self.listView = [[UITableView alloc]initWithFrame:CGRectMake(0, 44, self.frame.size.width, self.frame.size.height-44)];
84 | self.listView.backgroundColor = [UIColor clearColor];
85 | self.listView.delegate = self;
86 | self.listView.dataSource = self;
87 | [self.contentView addSubview:self.listView];
88 |
89 | //load data
90 | self.pathNames = [VZCrashInspector sharedInstance].crashPlist;
91 |
92 |
93 | //add subview
94 | self.subView = [[VZInspectorCrashView alloc]initWithFrame:CGRectMake(self.frame.size.width, 0, self.frame.size.width, self.frame.size.height)];
95 | self.subView.delegate = self;
96 | [self addSubview:self.subView];
97 |
98 | }
99 | return self;
100 | }
101 |
102 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
103 | {
104 | return 1;
105 | }
106 |
107 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
108 | {
109 | return self.pathNames.count;
110 | }
111 |
112 | - (UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
113 | {
114 | static NSString* sandCellId = @"crashIdentifier";
115 |
116 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:sandCellId];
117 | if (!cell) {
118 | cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:sandCellId];
119 | cell.backgroundColor = [UIColor clearColor];
120 | cell.textLabel.textColor = [UIColor orangeColor];
121 | cell.selectionStyle = UITableViewCellSelectionStyleNone;
122 | [cell addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onSelfClicked:)]];
123 | }
124 |
125 | cell.textLabel.text = self.pathNames[indexPath.row];
126 | cell.tag = indexPath.row;
127 |
128 |
129 | return cell;
130 | }
131 |
132 |
133 | - (void)onSelfClicked:(UITapGestureRecognizer* )tap
134 | {
135 | UIView* view = tap.view;
136 | NSInteger index = view.tag;
137 |
138 | if (index < self.pathNames.count) {
139 |
140 | NSString* path = self.pathNames[index];
141 | self.subView.path = path;
142 |
143 | [UIView animateWithDuration:0.4 animations:^{
144 |
145 | self.contentView.frame = CGRectMake(-CGRectGetWidth(self.bounds), 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
146 | self.subView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
147 |
148 | } completion:^(BOOL finished) {
149 |
150 | }];
151 |
152 | }
153 | }
154 |
155 | - (void)onBack {
156 | [UIView animateWithDuration:0.4 animations:^{
157 |
158 | self.contentView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
159 | self.subView.frame = CGRectMake(CGRectGetWidth(self.frame), 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
160 |
161 |
162 | } completion:^(BOOL finished) {
163 |
164 |
165 | }];
166 | }
167 |
168 | @end
169 |
170 |
171 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZInspectorCrashView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @protocol VZInspectorCrashViewCallBackProtocol
8 |
9 | @optional
10 | - (void)onBack;
11 |
12 |
13 | @end
14 |
15 |
16 | @interface VZInspectorCrashView : VZInspectorView
17 |
18 | @property(nonatomic,weak) id delegate;
19 | @property(nonatomic,strong) NSString* path;
20 |
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/crash/VZInspectorCrashView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #include
6 | #import "VZInspectorCrashView.h"
7 | #import "VZCrashInspector.h"
8 |
9 | @interface VZInspectorCrashView()
10 |
11 | @property(nonatomic,strong) UITextView* crashLogs;
12 | @property(nonatomic,strong) UILabel* textLabel;
13 | @property(nonatomic,strong) UIButton* backBtn;
14 |
15 | @end
16 |
17 | @implementation VZInspectorCrashView
18 |
19 | - (id)initWithFrame:(CGRect)frame
20 | {
21 | self = [super initWithFrame:frame];
22 | if (self) {
23 |
24 | self.textLabel = [[UILabel alloc]initWithFrame:CGRectMake(40, 0, frame.size.width-80, 44)];
25 | self.textLabel.text = @"CrashLogs";
26 | self.textLabel.textAlignment = NSTextAlignmentCenter;
27 | self.textLabel.textColor = [UIColor whiteColor];
28 | self.textLabel.backgroundColor = [UIColor clearColor];
29 | self.textLabel.font = [UIFont systemFontOfSize:18.0f];
30 | [self addSubview:self.textLabel];
31 |
32 | self.backBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 44, 44)];
33 | self.backBtn.backgroundColor = [UIColor clearColor];
34 | [self.backBtn setTitle:@"<-" forState:UIControlStateNormal];
35 | [self.backBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
36 | self.backBtn.titleLabel.font = [UIFont systemFontOfSize:18.0f];
37 |
38 | [self.backBtn addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
39 | #pragma clang diagnostic pop
40 | [self addSubview:self.backBtn];
41 |
42 |
43 | // Initialization code
44 | _crashLogs = [[UITextView alloc] initWithFrame:CGRectMake(0, 44 , frame.size.width, frame.size.height-44)];
45 | _crashLogs.font = [UIFont fontWithName:@"Courier-Bold" size:14];
46 | _crashLogs.textColor = [UIColor orangeColor];
47 | _crashLogs.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f];;
48 | _crashLogs.indicatorStyle = 0;
49 | _crashLogs.editable = NO;
50 | _crashLogs.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
51 | _crashLogs.layer.borderColor = [UIColor colorWithWhite:0.5f alpha:1.0f].CGColor;
52 | _crashLogs.layer.borderWidth = 2.0f;
53 | [self addSubview:_crashLogs];
54 |
55 | }
56 | return self;
57 | }
58 |
59 | - (void)setPath:(NSString *)path
60 | {
61 | _path = path;
62 |
63 | NSDictionary* logs = [[VZCrashInspector sharedInstance] crashForKey:path];
64 |
65 | NSString* header = @"crashes comes from => VZCrashInspector";
66 | header = [header stringByAppendingString:@"\n--------------------------------------\n"];
67 | _crashLogs.text = header;
68 |
69 | if (logs) {
70 |
71 | NSString* date = logs[@"date"];
72 | _crashLogs.text = [_crashLogs.text stringByAppendingString:[[@"> date :"stringByAppendingString:date] stringByAppendingString:@"\n"]];
73 |
74 | NSDictionary* info = logs[@"info"];
75 |
76 | //reason
77 | NSString* reason = info[@"reason"];
78 | _crashLogs.text = [[[_crashLogs.text stringByAppendingString:@"> reason: "] stringByAppendingString:reason] stringByAppendingString:@"\n"];
79 |
80 | //name
81 | NSString* name = info[@"name"];
82 | _crashLogs.text = [[[_crashLogs.text stringByAppendingString:@"> name: "] stringByAppendingString:name] stringByAppendingString:@"\n"];
83 |
84 | //call stack
85 | NSArray* callStack = info[@"callStack"];
86 | _crashLogs.text = [[[_crashLogs.text stringByAppendingString:@"> callStack: \n"] stringByAppendingString:[NSString stringWithFormat:@"%@",callStack]] stringByAppendingString:@"\n"];
87 |
88 | }
89 | }
90 |
91 | - (void)onBack
92 | {
93 | if (self.delegate) {
94 | [self.delegate onBack];
95 | }
96 | }
97 |
98 |
99 | @end
100 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/framerate/VZFrameRateOverlay.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZFrameRateOverlay : UIWindow
8 |
9 | +(instancetype)sharedInstance;
10 | +(void)start;
11 | +(void)stop;
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/framerate/VZFrameRateOverlay.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZFrameRateOverlay.h"
6 | #import "VZInspector.h"
7 | #import "VZInspectorResource.h"
8 | #import "VZInspectorOverlay.h"
9 |
10 | #define kVZHistoryTimeStampLength 42
11 |
12 | @interface VZFrameRateOverlay ()
13 | @property (nonatomic, strong) CADisplayLink *displayLink;
14 | @property (nonatomic, strong) UILabel *frameRateLabel;
15 | @property (nonatomic, assign) CFTimeInterval lastTimeStamp;
16 | @property (nonatomic, assign) CFTimeInterval *historyTimeStamp;
17 | @end
18 |
19 | @implementation VZFrameRateOverlay
20 |
21 | + (instancetype)sharedInstance {
22 | static VZFrameRateOverlay* instance = nil;
23 | static dispatch_once_t onceToken;
24 |
25 | dispatch_once(&onceToken, ^{
26 | int x = [UIScreen mainScreen].bounds.size.width > 320 ? 250 :180 ;
27 | instance = [[VZFrameRateOverlay alloc] initWithFrame:CGRectMake(x + 15, 0, 60, 20)];
28 | });
29 |
30 | return instance;
31 | }
32 |
33 | + (void)start {
34 | [VZInspectorOverlay sharedInstance].hidden = YES;
35 |
36 | VZFrameRateOverlay* o = [self sharedInstance];
37 | o.tag = 100;
38 | o.windowLevel = UIWindowLevelStatusBar+1;
39 | o.hidden = NO;
40 |
41 | o.displayLink.paused = NO;
42 | }
43 |
44 | + (void)stop {
45 | VZFrameRateOverlay* o = [self sharedInstance];
46 | o.hidden = YES;
47 |
48 | [VZInspectorOverlay sharedInstance].hidden = NO;
49 |
50 | o.displayLink.paused = YES;
51 | }
52 |
53 | - (id)initWithFrame:(CGRect)frame {
54 | self = [super initWithFrame:frame];
55 |
56 | if (self) {
57 | self.backgroundColor = [UIColor clearColor];
58 |
59 | _lastTimeStamp = CACurrentMediaTime();
60 | _historyTimeStamp = malloc(sizeof(CFTimeInterval) * kVZHistoryTimeStampLength);
61 |
62 | _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick:)];
63 | [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
64 | _displayLink.paused = YES;
65 |
66 | _frameRateLabel = [[UILabel alloc] initWithFrame:self.bounds];
67 | _frameRateLabel.font = [UIFont systemFontOfSize:12.f];
68 | _frameRateLabel.textColor = [UIColor orangeColor];
69 | _frameRateLabel.userInteractionEnabled = true;
70 | [_frameRateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onSelfClicked:)]];
71 | [self addSubview:_frameRateLabel];
72 |
73 | [[NSNotificationCenter defaultCenter] addObserver: self
74 | selector: @selector(applicationDidBecomeActiveNotification)
75 | name: UIApplicationDidBecomeActiveNotification
76 | object: nil];
77 |
78 | [[NSNotificationCenter defaultCenter] addObserver: self
79 | selector: @selector(applicationWillResignActiveNotification)
80 | name: UIApplicationWillResignActiveNotification
81 | object: nil];
82 | }
83 |
84 | return self;
85 | }
86 |
87 | - (void)applicationDidBecomeActiveNotification {
88 | if (!self.hidden) {
89 | [_displayLink setPaused:NO];
90 | }
91 | }
92 |
93 | - (void)applicationWillResignActiveNotification {
94 | if (!self.hidden) {
95 | [_displayLink setPaused:YES];
96 | }
97 | }
98 |
99 | - (void)displayLinkTick:(CADisplayLink *)displayLink {
100 | CFTimeInterval frameInterval = displayLink.timestamp - self.lastTimeStamp;
101 | NSUInteger totalCount = 0;
102 | CFTimeInterval totalInterval = 0;
103 |
104 | for (NSUInteger i = kVZHistoryTimeStampLength - 1; i > 0; i--) {
105 | self.historyTimeStamp[i] = self.historyTimeStamp[i - 1];
106 | totalCount++;
107 | totalInterval += self.historyTimeStamp[i - 1];
108 | }
109 | self.historyTimeStamp[0] = frameInterval;
110 | totalCount++;
111 | totalInterval += frameInterval;
112 |
113 | self.lastTimeStamp = displayLink.timestamp;
114 |
115 | self.frameRateLabel.text = [NSString stringWithFormat:@"%.ffps", 1 / (totalInterval / totalCount)];
116 | }
117 |
118 | - (void)onSelfClicked:(UILabel *)sender {
119 | if([VZInspector isShow])
120 | [VZInspector hide];
121 | else
122 | [VZInspector show];
123 | }
124 |
125 | - (void)becomeKeyWindow {
126 | //fix keywindow problem:
127 | //UIActionSheet在close后回重置keywindow,防止自己被设成keywindow
128 | [[[UIApplication sharedApplication].delegate window] makeKeyWindow];
129 | }
130 |
131 | @end
132 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/grid/UIWindow+VZInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface UIWindow (VZInspector)
8 |
9 | + (BOOL)isSwizzled;
10 | + (void)blockEvent:(BOOL) b;
11 | + (void)swizzle:(BOOL)b;
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/grid/UIWindow+VZInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "UIWindow+VZInspector.h"
6 | #include
7 | #include
8 | #include
9 | #import "VZInspectorOverlay.h"
10 |
11 |
12 | static bool g_blockEvent = false;
13 | static bool g_swizzled = false;
14 | static void (*g_sendEvent)(id,SEL,UIEvent* );
15 |
16 |
17 |
18 | @implementation UIWindow (VZInspector)
19 |
20 | + (BOOL)isSwizzled
21 | {
22 | UIWindow* keywindow = [UIApplication sharedApplication].keyWindow;
23 |
24 | if (keywindow == self)
25 | {
26 | return g_swizzled;
27 | }
28 | return NO;
29 | }
30 | + (void)blockEvent:(BOOL) b
31 | {
32 | g_blockEvent = b;
33 | }
34 |
35 | + (void)swizzle:(BOOL)b
36 | {
37 | g_swizzled = b;
38 |
39 | Method imp = class_getInstanceMethod([UIWindow class], @selector(sendEvent:));
40 |
41 | if (b) {
42 | g_sendEvent = (void* )class_getMethodImplementation([UIWindow class],@selector(sendEvent:));
43 | }
44 |
45 | IMP swizzleMethod = class_getMethodImplementation([UIWindow class], @selector(swizzle_SendEvent:));
46 |
47 |
48 | if (b) {
49 | method_setImplementation(imp, swizzleMethod);
50 | }
51 | else
52 | {
53 | method_setImplementation(imp, (IMP)g_sendEvent);
54 | }
55 |
56 | }
57 |
58 | - (void)swizzle_SendEvent:(UIEvent* )event
59 | {
60 | switch (event.type)
61 | {
62 | case UIEventTypeTouches:
63 | {
64 | NSSet * allTouches = [event allTouches];
65 |
66 | if ( 1 == [allTouches count] )
67 | {
68 | UITouch* touch = [allTouches allObjects][0];
69 |
70 | if (touch.tapCount == 1)
71 | {
72 | UIWindow* appWnd = [UIApplication sharedApplication].delegate.window;
73 |
74 | if (appWnd == self)
75 | {
76 | switch (touch.phase) {
77 |
78 | case UITouchPhaseBegan:
79 | {
80 | //NSLog( @"view '%@', touch began\n%@", [[touch.view class] description], [touch.view description] );
81 |
82 | UIView* border = [[UIView alloc]initWithFrame:CGRectMake(0, 0, touch.view.bounds.size.width, touch.view.bounds.size.height)];
83 | border.layer.borderColor = [UIColor redColor].CGColor;
84 | border.layer.borderWidth = 2.0f;
85 | border.layer.backgroundColor = [UIColor clearColor].CGColor;
86 | border.alpha = 0.8f;
87 | [touch.view addSubview:border];
88 |
89 |
90 | UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(0, 5, touch.view.bounds.size.width-10, 10)];
91 | label.text = [NSString stringWithFormat:@"[%.0f,%.0f,%.0f,%.0f]",touch.view.frame.origin.x,
92 | touch.view.frame.origin.y,
93 | touch.view.frame.size.width,
94 | touch.view.frame.size.height];
95 | label.textAlignment = NSTextAlignmentRight;
96 | label.textColor = [UIColor redColor];
97 | label.font = [UIFont systemFontOfSize:10.0f];
98 | label.backgroundColor = [UIColor clearColor];
99 | [touch.view addSubview:label];
100 |
101 | [UIView animateWithDuration:0.8 animations:^{
102 |
103 | border.alpha = 0.0f;
104 | label.alpha = 0.0f;
105 |
106 |
107 | } completion:^(BOOL finished) {
108 |
109 | [border removeFromSuperview];
110 | [label removeFromSuperview];
111 |
112 |
113 | }];
114 |
115 |
116 | break;
117 | }
118 | case UITouchPhaseMoved:
119 | {
120 | break;
121 | }
122 |
123 | case UITouchPhaseEnded:
124 | case UITouchPhaseCancelled:
125 | {
126 |
127 | break;
128 |
129 | }
130 | default:
131 | break;
132 | }//end of switch
133 | }//end of if
134 | else
135 | {
136 | [[self class] swizzle:NO];
137 |
138 | CGPoint pt = [touch locationInView:self];
139 |
140 | //show debugger:todo
141 | if (CGRectContainsPoint([VZInspectorOverlay sharedInstance].frame, pt)) {
142 | [[VZInspectorOverlay sharedInstance] sendEvent:event];
143 | }
144 | }
145 | }//end of if
146 |
147 | }//end of if
148 |
149 | break;
150 | }//end of case
151 | default:
152 | break;
153 | }//end of switch
154 |
155 | //pass event
156 | if (!g_blockEvent && g_sendEvent) {
157 | g_sendEvent(self,_cmd,event);
158 | }
159 | }
160 |
161 | @end
162 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/grid/VZInspectorGridView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorGridView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/grid/VZInspectorGridView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #include
6 | #import "VZInspectorGridView.h"
7 | #import "VZInspectorWindow.h"
8 |
9 | @implementation VZInspectorGridView
10 |
11 | - (id)initWithFrame:(CGRect)frame
12 | {
13 | self = [super initWithFrame:frame];
14 | if (self) {
15 | // Initialization code
16 | self.backgroundColor = [UIColor clearColor];
17 | //self.userInteractionEnabled = YES;
18 |
19 | UIButton* btn = [[UIButton alloc]initWithFrame:CGRectMake(300, 0, 20, 20)];
20 | btn.backgroundColor = [UIColor clearColor];
21 | btn.layer.cornerRadius = 10;
22 | btn.layer.masksToBounds = YES;
23 | btn.layer.borderColor = [UIColor redColor].CGColor;
24 | btn.layer.borderWidth = 1.0f;
25 | [btn setTitle:@"X" forState:UIControlStateNormal];
26 | [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
27 | [btn addTarget:self action:@selector(onClicked:) forControlEvents:UIControlEventTouchUpInside];
28 | [self addSubview:btn];
29 |
30 | }
31 | return self;
32 | }
33 |
34 |
35 | - (BOOL)canTouchPassThrough:(CGPoint)pt {
36 | return pt.y > 20;
37 | }
38 |
39 |
40 | - (void)drawRect:(CGRect)rect
41 | {
42 |
43 | // Drawing code
44 | CGContextRef context = UIGraphicsGetCurrentContext();
45 |
46 | //横线:
47 | int h = [UIScreen mainScreen].bounds.size.height;
48 | int w = [UIScreen mainScreen].bounds.size.width;
49 |
50 | for (int i=0; i<=h/20; i++) {
51 |
52 | [self drawSingleLine:context :(CGPoint){0, (i)*20} :(CGPoint){w,(i)*20} :[UIColor cyanColor] :0.5f];
53 |
54 | if (i%2 == 0) {
55 |
56 | NSString* str = [NSString stringWithFormat:@"%d",i*20];
57 |
58 | [[UIColor cyanColor] set];
59 | [str drawAtPoint:CGPointMake(0, (i*20)) withFont:[UIFont systemFontOfSize:8.0f]];
60 | }
61 | }
62 |
63 | //竖线:
64 | for (int i=0; i<=w/20; i++) {
65 |
66 | [self drawSingleLine:context :(CGPoint){i*20,0} :(CGPoint){i*20,h} :[UIColor cyanColor] : 0.5f];
67 |
68 | if (i % 2 == 0) {
69 | NSString* str = [NSString stringWithFormat:@"%d",i*20];
70 |
71 | [[UIColor cyanColor] set];
72 | [str drawAtPoint:CGPointMake((i*20),0) withFont:[UIFont systemFontOfSize:8.0f]];
73 |
74 | }
75 | }
76 | }
77 |
78 |
79 | - (void)onClicked:(id)sender
80 | {
81 |
82 | #pragma clang diagnostic push
83 | #pragma clang diagnostic ignored "-Wundeclared-selector"
84 | [self.parentViewController performSelector:@selector(onBack) withObject:nil];
85 | #pragma clang diagnostic pop
86 |
87 | }
88 |
89 | //draw a line
90 | - (void) drawSingleLine:(CGContextRef)context :(CGPoint) startPt :(CGPoint) endPt :(UIColor*) strokeColor :(CGFloat) strokeLineWidth
91 | {
92 | //CGFloat delta = strokeLineWidth/2;
93 | //CGFloat delta = 0;
94 |
95 | CGContextSaveGState(context);
96 | CGContextSetLineCap(context, kCGLineCapSquare);
97 | CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
98 | CGContextSetLineWidth(context, strokeLineWidth);
99 | CGContextSetShouldAntialias(context, NO );
100 | // CGContextMoveToPoint(context, startPt.x + delta, startPt.y + delta);
101 | // CGContextAddLineToPoint(context, endPt.x - delta, endPt.y - delta);
102 | CGContextMoveToPoint(context, startPt.x+0.5, startPt.y+0.5);
103 | CGContextAddLineToPoint(context, endPt.x+0.5, endPt.y+0.5);
104 | CGContextStrokePath(context);
105 | CGContextRestoreGState(context);
106 | }
107 |
108 |
109 | - (void)willMoveToWindow:(UIWindow *)newWindow
110 | {
111 | [super willMoveToWindow:newWindow];
112 |
113 | if ([self.parentViewController valueForKey:@"topView"] != self ) {
114 |
115 | // [UIWindow swizzle:YES];
116 | // [UIWindow blockEvent:YES];
117 | // [ETDebuggerWindow sharedInstance].backgroundColor = [UIColor clearColor];
118 | // [ETDebuggerWindow sharedInstance].alpha = 1.0f;
119 | [VZInspectorWindow sharedInstance].backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f];
120 | }
121 | else
122 | {
123 | // [UIWindow swizzle:NO];
124 | // [UIWindow blockEvent:NO];
125 | [VZInspectorWindow sharedInstance].backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f];
126 | }
127 |
128 | }
129 |
130 |
131 | @end
132 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/image/VZInspectorImageInfoView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorImageInfoView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/location/CLLocationManager+FLFake.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface CLLocationManager (FLFake)
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/location/CLLocationManager+FLFake.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "CLLocationManager+FLFake.h"
6 | #import
7 | #import "VZDefine.h"
8 | #import "FLFakeConfig.h"
9 |
10 | @implementation CLLocationManager (FLFake)
11 |
12 | + (void)load {
13 | Method originMethod = class_getInstanceMethod([CLLocationManager class], @selector(startUpdatingLocation));
14 | Method swizzleMethod = class_getInstanceMethod([CLLocationManager class], @selector(fl_startUpdatingLocation));
15 | method_exchangeImplementations(originMethod, swizzleMethod);
16 | }
17 |
18 | - (void)fl_startUpdatingLocation {
19 | NSLog(@"Start updating location");
20 | FLFakeConfig *fakeConfig = [FLFakeConfig sharedInstance];
21 | if (fakeConfig.enabled) {
22 | if (self.delegate) {
23 | if (!fequalzero(fakeConfig.delay)) {
24 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(fakeConfig.delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
25 | [self updateLocation:fakeConfig.location];
26 | });
27 | } else {
28 | [self updateLocation:fakeConfig.location];
29 | }
30 | }
31 | } else {
32 | [self fl_startUpdatingLocation];
33 | }
34 | }
35 |
36 | - (void)updateLocation:(CLLocation *)location {
37 | if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
38 | [self.delegate locationManager:self didUpdateLocations:@[location]];
39 | } else if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateToLocation:fromLocation:)]) {
40 | [self.delegate locationManager:self didUpdateToLocation:location fromLocation:location];
41 | }
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/location/FLFakeConfig.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import
7 |
8 | @interface FLFakeConfig : NSObject
9 |
10 | @property (nonatomic, assign) BOOL enabled;
11 | @property (nonatomic, readonly) CLLocation *location;
12 | @property (nonatomic, assign) CFTimeInterval delay;
13 |
14 | - (void)setLatitude:(CLLocationDegrees)latitude;
15 | - (void)setLongitude:(CLLocationDegrees)longitude;
16 |
17 | + (instancetype)sharedInstance;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/location/FLFakeConfig.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "FLFakeConfig.h"
6 | #import "VZDefine.h"
7 |
8 | @interface FLFakeConfig ()
9 |
10 | @property (nonatomic, strong) NSUserDefaults *userDefaults;
11 |
12 | @end
13 |
14 | static NSString * const kFLEnable = @"FLEnable";
15 | static NSString * const kFLLatitude = @"FLLatitude";
16 | static NSString * const kFLLongitude = @"FLLongitude";
17 | static NSString * const kFLDelay = @"FLDelay";
18 |
19 | @implementation FLFakeConfig
20 |
21 | + (instancetype)sharedInstance {
22 | static FLFakeConfig *instance;
23 | static dispatch_once_t onceToken;
24 | dispatch_once(&onceToken, ^{
25 | instance = [[self alloc] init];
26 | });
27 | return instance;
28 | }
29 |
30 | - (instancetype)init {
31 | self = [super init];
32 | if (self) {
33 | _userDefaults = [[NSUserDefaults alloc]initWithUser:@"com.johnwong.FakeLocation"];
34 | }
35 | return self;
36 | }
37 |
38 | - (void)setEnabled:(BOOL)enabled {
39 | [_userDefaults setValue:@(enabled) forKey:kFLEnable];
40 | [_userDefaults synchronize];
41 | }
42 |
43 | - (void)setLatitude:(CLLocationDegrees)latitude {
44 | [_userDefaults setValue:@(latitude) forKey:kFLLatitude];
45 | [_userDefaults synchronize];
46 | }
47 |
48 | - (void)setLongitude:(CLLocationDegrees)longitude {
49 | [_userDefaults setValue:@(longitude) forKey:kFLLongitude];
50 | [_userDefaults synchronize];
51 | }
52 |
53 | - (void)setDelay:(CFTimeInterval)delay {
54 | [_userDefaults setValue:@(delay) forKey:kFLDelay];
55 | [_userDefaults synchronize];
56 | }
57 |
58 | - (BOOL)enabled {
59 | id value = [_userDefaults valueForKey:kFLEnable];
60 | return value? [value boolValue] : NO;
61 | }
62 |
63 | - (CLLocation *)location {
64 | CLLocationDegrees latitude = [[_userDefaults valueForKey:kFLLatitude] doubleValue];
65 | CLLocationDegrees longitude = [[_userDefaults valueForKey:kFLLongitude] doubleValue];
66 | if (fequalzero(latitude) && fequalzero(longitude)) {
67 | latitude = 30.26667;
68 | longitude = 120.2;
69 | }
70 | return [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
71 | }
72 |
73 | - (CFTimeInterval)delay {
74 | return [[_userDefaults valueForKey:kFLDelay] doubleValue];
75 | }
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/location/VZInspectorLocationView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorLocationView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZInspectorNetworkDetailView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @protocol VZInspectorNetworkDetailView
8 |
9 | - (void)onDetailBack;
10 | @end
11 |
12 | @class VZNetworkTransaction;
13 | @interface VZInspectorNetworkDetailView : UIView
14 |
15 | @property(nonatomic,strong) VZNetworkTransaction* transaction;
16 | @property(nonatomic,weak) id delegate;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZInspectorNetworkHistoryView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorNetworkHistoryView : VZInspectorView
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkInspector.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "VZNetworkTransaction.h"
7 |
8 | extern NSString* const kVZNetworkInspectorRequestNotification;
9 | extern NSString* const kVZNetworkInspectorRequestFinishedNotification;
10 |
11 | typedef NSString *(^TransactionTitleFilter)(VZNetworkTransaction *transaction);
12 | typedef NSString *(^VZNetworkDecoder)(VZNetworkTransaction *transaction, NSData *data);
13 |
14 | @interface VZNetworkInspector : NSObject
15 | + (instancetype)sharedInstance;
16 |
17 | @property(nonatomic,assign) size_t totalResponseBytes;
18 | @property(nonatomic,assign) NSInteger totalNetworkCount;
19 |
20 | - (void)addTransactionTitleFilter:(TransactionTitleFilter)filter;
21 | - (NSArray *)transactionTitleFilters;
22 | + (void)setIgnoreDelegateClasses:(NSSet *)classes;
23 |
24 | - (void)addRequestDecoder:(VZNetworkDecoder)decoder;
25 | - (void)addResponseDecoder:(VZNetworkDecoder)decoder;
26 |
27 | @property (nonatomic, strong, readonly) NSMutableArray *requestDecoders;
28 | @property (nonatomic, strong, readonly) NSMutableArray *responseDecoders;
29 |
30 | - (NSString *)decodeRequestData:(NSData *)data withTransaction:(VZNetworkTransaction *)transaction;
31 | - (NSString *)decodeResponseData:(NSData *)data withTransaction:(VZNetworkTransaction *)transaction;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkInspector.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZNetworkInspector.h"
6 | #import "NSObject+VZInspector.h"
7 | #import "VZLogInspector.h"
8 | #import "VZNetworkObserver.h"
9 |
10 |
11 | NSString* const kVZNetworkInspectorRequestNotification = @"VZNetworkInspectorRequestNotification";
12 | NSString* const kVZNetworkInspectorRequestFinishedNotification = @"VZNetworkInspectorRequestFinishedNotification";
13 |
14 |
15 | @interface VZNetworkInspector()
16 |
17 | @property(nonatomic,assign) NSInteger networkCount;
18 |
19 | @end
20 |
21 | @implementation VZNetworkInspector {
22 | NSMutableArray *_titleFilters;
23 | }
24 |
25 | + (instancetype)sharedInstance
26 | {
27 | static VZNetworkInspector* instance;
28 | static dispatch_once_t onceToken;
29 | dispatch_once(&onceToken, ^{
30 | instance = [VZNetworkInspector new];
31 | });
32 | return instance;
33 | }
34 |
35 | - (id)init
36 | {
37 | self = [super init];
38 |
39 | if (self) {
40 | _titleFilters = [NSMutableArray array];
41 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRequestReceived:) name:kVZNetworkInspectorRequestNotification object:nil];
42 |
43 | _requestDecoders = [NSMutableArray array];
44 | _responseDecoders = [NSMutableArray array];
45 |
46 | }
47 | return self;
48 | }
49 |
50 | - (void)dealloc
51 | {
52 | [[NSNotificationCenter defaultCenter] removeObserver:self];
53 | }
54 |
55 | - (void)onRequestReceived:(NSNotification* )notify
56 | {
57 | self.totalNetworkCount ++ ;
58 | self.networkCount ++;
59 |
60 | if (self.samplePoints == nil)
61 | self.samplePoints = [NSMutableArray new];
62 |
63 | [self.samplePoints addObject:@(self.networkCount)];
64 | [self.samplePoints addObject:@(self.networkCount)];
65 |
66 | self.networkCount --;
67 | [self.samplePoints addObject:@(self.networkCount)];
68 | [self.samplePoints addObject:@(self.networkCount)];
69 |
70 |
71 | NSNumber* len = notify.userInfo[@"data-len"];
72 | self.totalResponseBytes += len.longValue;
73 | }
74 |
75 | - (void)onRequestFinished:(NSNotification* )notify
76 | {
77 |
78 | }
79 |
80 |
81 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////
82 | #pragma mark - for debugger use
83 |
84 | - (void)vz_heartBeat
85 | {
86 |
87 | if (self.samplePoints == nil)
88 | self.samplePoints = [NSMutableArray new];
89 |
90 | // NSLog(@"request:%d",self.networkCount);
91 |
92 | [self.samplePoints addObject:@(self.networkCount)];
93 |
94 | //keep last 50 points
95 | if ( [self.samplePoints count] > 50 )
96 | {
97 | NSRange range;
98 | range.location = 0;
99 | range.length = [self.samplePoints count] - 50;
100 | [self.samplePoints removeObjectsInRange:range];
101 | }
102 |
103 | }
104 |
105 | - (void)addTransactionTitleFilter:(TransactionTitleFilter)filter
106 | {
107 | [_titleFilters addObject:filter];
108 | }
109 |
110 | - (NSArray *)transactionTitleFilters
111 | {
112 | return [_titleFilters copy];
113 | }
114 |
115 | + (void)setIgnoreDelegateClasses:(NSSet *)classes
116 | {
117 | [VZNetworkObserver setIgnoreDelegateClasses:classes];
118 | }
119 |
120 | - (void)addRequestDecoder:(VZNetworkDecoder)decoder
121 | {
122 | if (decoder) {
123 | [_requestDecoders addObject:decoder];
124 | }
125 | }
126 |
127 | - (void)addResponseDecoder:(VZNetworkDecoder)decoder
128 | {
129 | if (decoder) {
130 | [_responseDecoders addObject:decoder];
131 | }
132 | }
133 |
134 | - (NSString *)decodeRequestData:(NSData *)data withTransaction:(VZNetworkTransaction *)transaction
135 | {
136 | for (VZNetworkDecoder decoder in [VZNetworkInspector sharedInstance].requestDecoders) {
137 | NSString *result = decoder(transaction, data);
138 | if (result.length > 0) {
139 | return result;
140 | }
141 | }
142 | return nil;
143 | }
144 |
145 | - (NSString *)decodeResponseData:(NSData *)data withTransaction:(VZNetworkTransaction *)transaction
146 | {
147 | for (VZNetworkDecoder decoder in [VZNetworkInspector sharedInstance].responseDecoders) {
148 | NSString *result = decoder(transaction, data);
149 | if (result.length > 0) {
150 | return result;
151 | }
152 | }
153 | return nil;
154 | }
155 |
156 | @end
157 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkInspectorOverView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 | //
5 | //#import
6 | //
7 | //@interface VZNetworkInspectorOverView : UIView
8 | //
9 | //- (void)handleRead;
10 | //- (void)handleWrite;
11 | //
12 | //@end
13 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkInspectorOverView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 | //
5 | //#include
6 | //#import "VZNetworkInspectorOverView.h"
7 | //#import "VZInspectorPlotView.h"
8 | //#import "NSObject+VZInspector.h"
9 | //#import "VZNetworkInspector.h"
10 | //
11 | //
12 | //
13 | //@implementation VZNetworkInspectorOverView
14 | //{
15 | // UILabel * _titleView;
16 | // UILabel * _statusView;
17 | // VZInspectorPlotView* _plotView1;
18 | //}
19 | //
20 | //- (id)initWithFrame:(CGRect)frame
21 | //{
22 | // self = [super initWithFrame:frame];
23 | // if (self) {
24 | //
25 | // //self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f];
26 | // self.layer.borderColor = [UIColor colorWithWhite:0.5f alpha:1.0f].CGColor;
27 | // self.layer.borderWidth = 1.0f;
28 | //
29 | // CGRect plotFrame;
30 | // plotFrame.size.width = frame.size.width;
31 | // plotFrame.size.height = frame.size.height - 20.0f;
32 | // plotFrame.origin.x = 0.0f;
33 | // plotFrame.origin.y = 20.0f;
34 | //
35 | // //draw http connection pool
36 | // _plotView1 = [[VZInspectorPlotView alloc] initWithFrame:plotFrame];
37 | // _plotView1.alpha = 0.6f;
38 | // _plotView1.lowerBound = 0.0f;
39 | // _plotView1.upperBound = 0.0f;
40 | // _plotView1.lineColor = [UIColor yellowColor];
41 | // _plotView1.lineWidth = 2.0f;
42 | // _plotView1.capacity = 50;
43 | // _plotView1.fill = NO;
44 | // [self addSubview:_plotView1];
45 | //
46 | //
47 | // CGRect titleFrame;
48 | // titleFrame.size.width = 120.0f;
49 | // titleFrame.size.height = 20.0f;
50 | // titleFrame.origin.x = 8.0f;
51 | // titleFrame.origin.y = 0.0f;
52 | //
53 | // _titleView = [[UILabel alloc] initWithFrame:titleFrame];
54 | // _titleView.textColor = [UIColor orangeColor];
55 | // _titleView.textAlignment = NSTextAlignmentLeft;
56 | // _titleView.font = [UIFont boldSystemFontOfSize:12.0f];
57 | // _titleView.lineBreakMode = NSLineBreakByClipping;
58 | // _titleView.backgroundColor = [UIColor clearColor];
59 | // _titleView.numberOfLines = 1;
60 | // _titleView.text = @"Network";
61 | // [self addSubview:_titleView];
62 | //
63 | // CGRect statusFrame;
64 | // statusFrame.size.width = 200;
65 | // statusFrame.size.height = 20.0f;
66 | // statusFrame.origin.x = frame.size.width - 200 -10;
67 | // statusFrame.origin.y = 0.0f;
68 | //
69 | // _statusView = [[UILabel alloc] initWithFrame:statusFrame];
70 | // _statusView.textColor = [UIColor whiteColor];
71 | // _statusView.textAlignment = NSTextAlignmentRight;
72 | // _statusView.font = [UIFont boldSystemFontOfSize:12.0f];
73 | // _statusView.lineBreakMode = NSLineBreakByClipping;
74 | // _statusView.numberOfLines = 1;
75 | // _statusView.backgroundColor = [UIColor clearColor];
76 | // [self addSubview:_statusView];
77 | //
78 | // }
79 | // return self;
80 | //}
81 | //
82 | //- (void)handleRead
83 | //{
84 | // [[VZNetworkInspector sharedInstance] vz_heartBeat];
85 | //}
86 | //- (void)handleWrite
87 | //{
88 | // [self writeHeartBeat];
89 | //}
90 | //
91 | //- (void)writeHeartBeat
92 | //{
93 | //
94 | // NSMutableString * text = [NSMutableString string];
95 | // [text appendFormat:@"Count: %ld",(long)[VZNetworkInspector sharedInstance].totalNetworkCount];
96 | // [text appendFormat:@" Bytes:%@ ",[self number2String:[VZNetworkInspector sharedInstance].totalResponseBytes]];
97 | //
98 | // _statusView.text = text;
99 | //
100 | // //http connection pool
101 | // NSArray* tmp2 = [VZNetworkInspector sharedInstance].samplePoints.copy;
102 | // CGFloat _upperBound2 = 1;
103 | // CGFloat _lowerBound2 = 0;
104 | //
105 | // for ( NSNumber * n in tmp2 )
106 | // {
107 | // if ( n.intValue > _upperBound2 )
108 | // {
109 | // _upperBound2 = n.intValue;
110 | // if ( _upperBound2 < _lowerBound2 )
111 | // {
112 | // _lowerBound2 = _upperBound2;
113 | // }
114 | // }
115 | // else if ( n.intValue < _lowerBound2 )
116 | // {
117 | // _lowerBound2 = n.intValue;
118 | // }
119 | // }
120 | //
121 | // [_plotView1 setPlots:tmp2];
122 | // [_plotView1 setLowerBound:_lowerBound2];
123 | // [_plotView1 setUpperBound:_upperBound2];
124 | // [_plotView1 setNeedsDisplay];
125 | //
126 | //}
127 | //#define KB (1024)
128 | //#define MB (KB * 1024)
129 | //#define GB (MB * 1024)
130 | //
131 | //- (NSString* )number2String:(int64_t)n
132 | //{
133 | // if ( n < KB )
134 | // {
135 | // return [NSString stringWithFormat:@"%lldB", n];
136 | // }
137 | // else if ( n < MB )
138 | // {
139 | // return [NSString stringWithFormat:@"%.1fK", (float)n / (float)KB];
140 | // }
141 | // else if ( n < GB )
142 | // {
143 | // return [NSString stringWithFormat:@"%.1fM", (float)n / (float)MB];
144 | // }
145 | // else
146 | // {
147 | // return [NSString stringWithFormat:@"%.1fG", (float)n / (float)GB];
148 | // }
149 | //}
150 | //
151 | //
152 | //@end
153 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkObserver.h:
--------------------------------------------------------------------------------
1 | //
2 | // VZNetworkObserver.h
3 | // Derived from:
4 | //
5 | // FLEXNetworkObserver
6 | // Flipboard
7 | //
8 | // Created by Ryan Olson
9 | // Copyright (c) 2015 Flipboard. All rights reserved.
10 | //
11 |
12 |
13 |
14 | #import
15 |
16 | extern NSString *const kVZNetworkObserverEnabledStateChangedNotification;
17 |
18 |
19 | @interface VZNetworkObserver : NSObject
20 |
21 |
22 | + (void)setEnabled:(BOOL)enabled;
23 | + (BOOL)isEnabled;
24 |
25 | + (void)setShouldEnableOnLaunch:(BOOL)shouldEnableOnLaunch;
26 | + (BOOL)shouldEnableOnLaunch;
27 | + (void)setIgnoreDelegateClasses:(NSSet *)classes;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkRecorder.h:
--------------------------------------------------------------------------------
1 | //
2 | // VZNetworkObserver.h
3 | // Derived from:
4 | // Flipboard
5 | //
6 | // Created by Ryan Olson on 2/4/15.
7 | // Copyright (c) 2015 Flipboard. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 |
13 | @class VZNetworkTransaction;
14 |
15 |
16 | @interface VZNetworkRecorder : NSObject
17 |
18 |
19 | /// In general, it only makes sense to have one recorder for the entire application.
20 | + (instancetype)defaultRecorder;
21 |
22 | /// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.
23 | @property (nonatomic, assign) NSUInteger responseCacheByteLimit;
24 |
25 | /// If NO, the recorder not cache will not cache response for content types with an "image", "video", or "audio" prefix.
26 | @property (nonatomic, assign) BOOL shouldCacheMediaResponses;
27 |
28 | // Accessing recorded network activity
29 |
30 | /// Array of VZNetworkTransaction objects ordered by start time with the newest first.
31 | - (NSArray *)networkTransactions;
32 |
33 | /// The full response data IFF it hasn't been purged due to memory pressure.
34 | - (NSData *)cachedResponseBodyForTransaction:(VZNetworkTransaction *)transaction;
35 |
36 | /// Dumps all network transactions and cached response bodies.
37 | - (void)clearRecordedActivity;
38 |
39 |
40 | // Recording network activity
41 |
42 | /// Call when app is about to send HTTP request.
43 | - (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
44 |
45 | /// Call when HTTP response is available.
46 | - (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response;
47 |
48 | /// Call when data chunk is received over the network.
49 | - (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength;
50 |
51 | /// Call when HTTP request has finished loading.
52 | - (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody;
53 |
54 | /// Call when HTTP request has failed to load.
55 | - (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error;
56 |
57 | /// Call to set the request mechanism anytime after recordRequestWillBeSent... has been called.
58 | /// This string can be set to anything useful about the API used to make the request.
59 | - (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID;
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkTransaction.h:
--------------------------------------------------------------------------------
1 | //
2 | // VZNetworkObserver.h
3 | // Derived from:
4 | //
5 | // VZNetworkTransaction
6 | // Flipboard
7 | //
8 | // Created by Ryan Olson on 2/8/15.
9 | // Copyright (c) 2015 Flipboard. All rights reserved.
10 | //
11 |
12 | #import
13 |
14 | typedef NS_ENUM(NSInteger, VZNetworkTransactionState) {
15 | VZNetworkTransactionStateUnstarted,
16 | VZNetworkTransactionStateAwaitingResponse,
17 | VZNetworkTransactionStateReceivingData,
18 | VZNetworkTransactionStateFinished,
19 | VZNetworkTransactionStateFailed
20 | };
21 |
22 | @interface VZNetworkTransaction : NSObject
23 |
24 | @property (nonatomic, copy) NSString *requestID;
25 |
26 | @property (nonatomic, strong) NSURLRequest *request;
27 | @property (nonatomic, strong) NSURLResponse *response;
28 | @property (nonatomic, copy) NSString *requestMechanism;
29 | @property (nonatomic, assign) VZNetworkTransactionState transactionState;
30 | @property (nonatomic, strong) NSError *error;
31 |
32 | @property (nonatomic, strong) NSDate *startTime;
33 | @property (nonatomic, assign) NSTimeInterval latency;
34 | @property (nonatomic, assign) NSTimeInterval duration;
35 | @property (nonatomic, assign) int64_t gzipDataLength;
36 | @property (nonatomic, assign) int64_t receivedDataLength;
37 |
38 | @property (nonatomic, strong, readonly) NSData *postBodyData;
39 |
40 | /// Only applicable for image downloads. A small thumbnail to preview the full response.
41 | //@property (nonatomic, strong) UIImage *responseThumbnail;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/network/VZNetworkTransaction.m:
--------------------------------------------------------------------------------
1 | //
2 | // VZNetworkObserver.m
3 | // Derived from:
4 | //
5 | // VZNetworkTransaction
6 | // Flipboard
7 | //
8 | // Created by Ryan Olson on 2/8/15.
9 | // Copyright (c) 2015 Flipboard. All rights reserved.
10 |
11 | #import "VZNetworkTransaction.h"
12 | #import "VZInspectorUtility.h"
13 |
14 | @implementation VZNetworkTransaction
15 |
16 | @synthesize postBodyData = _postBodyData;
17 |
18 | - (NSString *)description
19 | {
20 | NSString *description = [super description];
21 |
22 | description = [description stringByAppendingFormat:@" id = %@;", self.requestID];
23 | description = [description stringByAppendingFormat:@" url = %@;", self.request.URL];
24 | description = [description stringByAppendingFormat:@" duration = %f;", self.duration];
25 | description = [description stringByAppendingFormat:@" receivedDataLength = %lld", self.receivedDataLength];
26 |
27 | NSString* stateStr = @"";
28 | switch (self.transactionState) {
29 | case VZNetworkTransactionStateUnstarted:
30 | stateStr = @"state = Unstarted";
31 | break;
32 |
33 | case VZNetworkTransactionStateAwaitingResponse:
34 | stateStr = @"state = Awaiting Response";
35 | break;
36 |
37 | case VZNetworkTransactionStateReceivingData:
38 | stateStr = @"state = Receiving Data";
39 | break;
40 |
41 | case VZNetworkTransactionStateFinished:
42 | stateStr = @"state = Finished";
43 | break;
44 |
45 | case VZNetworkTransactionStateFailed:
46 | stateStr = @"state = Failed";
47 | break;
48 | }
49 |
50 | return [description stringByAppendingString:stateStr];
51 | }
52 |
53 | - (NSData *)postBodyData
54 | {
55 | if (!_postBodyData) {
56 | NSData *bodyData = self.request.HTTPBody;
57 | if ([bodyData length] > 0) {
58 | NSString *contentEncoding = [self.request valueForHTTPHeaderField:@"Content-Encoding"];
59 | if ([contentEncoding rangeOfString:@"deflate" options:NSCaseInsensitiveSearch].length > 0 || [contentEncoding rangeOfString:@"gzip" options:NSCaseInsensitiveSearch].length > 0) {
60 | bodyData = [VZInspectorUtility inflatedDataFromCompressedData:bodyData];
61 | }
62 | }
63 | _postBodyData = bodyData;
64 | }
65 | return _postBodyData;
66 | }
67 |
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/sandbox/VZInspectorSandBoxRootView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "VZInspectorView.h"
6 |
7 | @interface VZInspectorSandBoxRootView : VZInspectorView
8 |
9 |
10 |
11 | @end
12 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/sandbox/VZInspectorSandBoxRootView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #include
6 | #import "VZInspectorSandBoxRootView.h"
7 | #import "VZInspectorSandBoxSubView.h"
8 |
9 |
10 | @interface VZInspectorSandBoxHeaderView : UIView
11 |
12 | @property(nonatomic,strong) UILabel* textLabel;
13 | @property(nonatomic,strong) UIButton* backBtn;
14 | @property(nonatomic,weak) id delegate;
15 |
16 | @end
17 |
18 | @implementation VZInspectorSandBoxHeaderView
19 |
20 | - (id)initWithFrame:(CGRect)frame
21 | {
22 | self = [super initWithFrame:frame];
23 |
24 | if (self) {
25 |
26 | self.textLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 13, frame.size.width, 18)];
27 | self.textLabel.textAlignment = NSTextAlignmentCenter;
28 | self.textLabel.textColor = [UIColor whiteColor];
29 | self.textLabel.backgroundColor = [UIColor clearColor];
30 | self.textLabel.font = [UIFont systemFontOfSize:18.0f];
31 | [self addSubview:self.textLabel];
32 |
33 | self.backBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 44, 44)];
34 | self.backBtn.backgroundColor = [UIColor clearColor];
35 | [self.backBtn setTitle:@"<-" forState:UIControlStateNormal];
36 | [self.backBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
37 | self.backBtn.titleLabel.font = [UIFont systemFontOfSize:18.0f];
38 | #pragma clang diagnostic push
39 | #pragma clang diagnostic ignored "-Wundeclared-selector"
40 | [self.backBtn addTarget:self.delegate action:@selector(pop) forControlEvents:UIControlEventTouchUpInside];
41 | #pragma clang diagnostic pop
42 | [self addSubview:self.backBtn];
43 | }
44 | return self;
45 | }
46 |
47 | @end
48 |
49 | @interface VZInspectorSandBoxRootView()
50 |
51 | @property(nonatomic,strong)NSMutableArray* stack;
52 | @property(nonatomic,strong)VZInspectorSandBoxHeaderView* headerView;
53 | @property(nonatomic,strong)NSString* homepath;
54 | @property(nonatomic,strong)NSString* filepath;
55 | @property(nonatomic,strong)NSString* filename;
56 | @property(nonatomic,strong)VZInspectorSandBoxSubView* currentView;
57 |
58 | @end
59 |
60 | @implementation VZInspectorSandBoxRootView
61 |
62 | - (id)initWithFrame:(CGRect)frame
63 | {
64 | self = [super initWithFrame:frame];
65 |
66 | if (self) {
67 |
68 | self.stack = [NSMutableArray new];
69 | self.homepath = NSHomeDirectory();
70 |
71 | self.headerView = [[VZInspectorSandBoxHeaderView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, 44)];
72 | self.headerView.delegate = self;
73 | [self addSubview:self.headerView];
74 |
75 | [self loadRootView];
76 |
77 | }
78 | return self;
79 | }
80 |
81 | - (void)loadRootView
82 | {
83 | VZInspectorSandBoxSubView* rootView = [[VZInspectorSandBoxSubView alloc]initWithFrame:CGRectMake(0, 44, self.frame.size.width, self.frame.size.height-44) dir:self.homepath appendBundle:YES];
84 | rootView.layer.borderColor = [UIColor colorWithWhite:0.5f alpha:1.0f].CGColor;
85 | rootView.layer.borderWidth = 2.0f;
86 | rootView.delegate = self;
87 |
88 |
89 | [self.stack addObject:rootView];
90 | [self addSubview:rootView];
91 | self.currentView = rootView;
92 | self.filename = @"Root";
93 | self.filepath = self.homepath;
94 | self.headerView.textLabel.text = self.filename;
95 |
96 | }
97 |
98 | - (void)push
99 | {
100 | VZInspectorSandBoxSubView* targetView = [[VZInspectorSandBoxSubView alloc]initWithFrame:CGRectMake(self.frame.size.width, 44, self.frame.size.width, self.frame.size.height-44) dir:self.filepath appendBundle:NO];
101 | targetView.delegate = self;
102 | targetView.alpha = 0.0f;
103 | [self addSubview:targetView];
104 |
105 |
106 | VZInspectorSandBoxSubView* currentView = self.currentView;
107 |
108 | [UIView animateWithDuration:0.4 animations:^{
109 |
110 | currentView.alpha = 0.0f;
111 | currentView.frame = CGRectMake(-CGRectGetWidth(currentView.bounds), 44, CGRectGetWidth(currentView.bounds), CGRectGetHeight(currentView.bounds));
112 |
113 | targetView.frame = CGRectMake(0, 44, CGRectGetWidth(targetView.bounds), CGRectGetHeight(targetView.bounds));
114 | targetView.alpha = 1.0f;
115 |
116 | } completion:^(BOOL finished) {
117 |
118 | [self.stack addObject:targetView];
119 | currentView.frame = CGRectMake(0, 0, CGRectGetWidth(currentView.bounds), CGRectGetHeight(currentView.bounds));
120 | self.currentView = targetView;
121 | }];
122 |
123 | }
124 |
125 | - (void)pop
126 | {
127 | if (self.stack.count <2) {
128 |
129 | #pragma clang diagnostic push
130 | #pragma clang diagnostic ignored "-Wundeclared-selector"
131 | [self.parentViewController performSelector:@selector(onBack)];
132 | #pragma clang diagnostic pop
133 |
134 | }
135 | else
136 | {
137 | VZInspectorSandBoxSubView* currentView = self.currentView;
138 | currentView.alpha = 1.0f;
139 |
140 | VZInspectorSandBoxSubView* belowView = self.stack[self.stack.count - 2];
141 | belowView.alpha = 0.0f;
142 |
143 | belowView.frame = CGRectMake(-CGRectGetWidth(belowView.bounds), 44, CGRectGetWidth(belowView.bounds), CGRectGetHeight(belowView.bounds));
144 | [UIView animateWithDuration:0.4 animations:^{
145 |
146 | currentView.frame = CGRectMake(self.frame.size.width, 44, CGRectGetWidth(currentView.bounds), CGRectGetHeight(currentView.bounds));
147 | currentView.alpha = 0.0f;
148 |
149 | belowView.frame = CGRectMake(0, 44,CGRectGetWidth(belowView.bounds), CGRectGetHeight(belowView.bounds));
150 | belowView.alpha = 1.0f;
151 |
152 | } completion:^(BOOL finished) {
153 |
154 |
155 | [self.stack removeObject:currentView];
156 | [currentView removeFromSuperview];
157 | self.currentView = belowView;
158 | //self.headerView.textLabel.text = self.currentView.currentDir;
159 |
160 |
161 | }];
162 | }
163 | }
164 |
165 | - (void)onSubViewDidSelect:(NSInteger)index FileName:(NSString *)file
166 | {
167 | self.filepath = file;
168 | [self push];
169 |
170 | }
171 |
172 |
173 | @end
174 |
--------------------------------------------------------------------------------
/VZInspector/toolbox/sandbox/VZInspectorSandBoxSubView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface VZInspectorSandBoxItem : NSObject
8 |
9 | @property(nonatomic,strong) NSString* name;
10 | @property(nonatomic,strong) NSString* path;
11 |
12 | @end
13 |
14 |
15 | @protocol VZInspectorSandBoxSubViewCallBackProtocol
16 |
17 | @optional
18 | - (void)onSubViewDidSelect:(NSInteger)index FileName:(NSString* )file;
19 | @end
20 |
21 | @interface VZInspectorSandBoxSubView : UIView
22 |
23 | @property(nonatomic,weak) id delegate;
24 | @property(nonatomic,strong)NSString* currentDir;
25 |
26 | - (id)initWithFrame:(CGRect)frame dir:(NSString* )dir appendBundle:(BOOL)appendBundle;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/VZInspectorDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/VZInspectorDemo.xcodeproj/xcshareddata/xcschemes/VZInspectorDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/VZInspectorDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface AppDelegate : UIResponder
8 |
9 | @property (strong, nonatomic) UIWindow *window;
10 |
11 |
12 | @end
13 |
14 |
--------------------------------------------------------------------------------
/VZInspectorDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import "AppDelegate.h"
6 | #import "VZInspector.h"
7 |
8 | @interface AppDelegate ()
9 |
10 | @end
11 |
12 | @implementation AppDelegate
13 |
14 |
15 |
16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
17 |
18 | [VZInspector setClassPrefixName:@"VZ"];
19 | [VZInspector setShouldHandleCrash:true];
20 | [VZInspector setShouldHookNetworkRequest:true];
21 | [VZInspector setLogNumbers:10];
22 | [VZInspector addObserveCallback:^NSString *{
23 |
24 | NSString* v = [NSString stringWithFormat:@"System Ver:%@\n",[UIDevice currentDevice].systemVersion];
25 | NSString* n = [NSString stringWithFormat:@"System Name:%@\n",[UIDevice currentDevice].systemName];
26 | NSString* ret = [v stringByAppendingString:n];
27 | return ret;
28 | }];
29 |
30 | //add custom plugin
31 | [self addCustomPlugin];
32 | [VZInspector showOnStatusBar];
33 |
34 | return YES;
35 | }
36 |
37 | - (void)addCustomPlugin{
38 |
39 | #if TARGET_OS_SIMULATOR
40 | u_int8_t bytesIcon[] = {0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x3c,0x0,0x0,0x0,0x3c,0x8,0x3,0x0,0x0,0x0,0xd,0x22,0x29,0x40,0x0,0x0,0x0,0x42,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0xff,0x80,0x20,0xfd,0x80,0x22,0xff,0x82,0x20,0xfc,0x80,0x23,0xfd,0x81,0x22,0xff,0x80,0x20,0xfd,0x80,0x22,0xfc,0x80,0x23,0xfc,0x80,0x23,0xff,0x80,0x20,0xfd,0x80,0x22,0xfd,0x80,0x22,0xfd,0x80,0x23,0xfd,0x80,0x22,0xfd,0x80,0x22,0xfd,0x7f,0x22,0xfd,0x80,0x22,0xff,0x80,0x20,0xfd,0x80,0x22,0xfd,0x80,0x22,0xfd,0x80,0x23,0xcd,0xd0,0x2,0x56,0x0,0x0,0x0,0x15,0x74,0x52,0x4e,0x53,0x0,0x40,0x80,0x3f,0xc0,0x7f,0x30,0xef,0x60,0xbf,0x20,0xe0,0x9f,0xa0,0xdf,0xd0,0x90,0xcf,0x10,0x70,0xf0,0x42,0x95,0x4e,0x90,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x78,0x5e,0xed,0xd5,0xcb,0xe,0x84,0x20,0xc,0x86,0x51,0xa8,0x1d,0x1c,0xf0,0x32,0x57,0xdf,0xff,0x55,0xc7,0x5,0x9,0xf9,0x49,0x98,0xd2,0x5d,0x35,0x7e,0x1b,0x6c,0xcc,0x59,0x11,0xc0,0x1d,0xbb,0x34,0x48,0xa5,0x36,0xa6,0x4d,0x6a,0xc,0x2,0x56,0x68,0xc4,0x6a,0x8d,0x78,0xa1,0x56,0xcf,0xa2,0x5b,0xd8,0xbb,0x66,0x77,0xd4,0x32,0x96,0x35,0x62,0xa5,0x46,0xac,0xd4,0x88,0x95,0x1a,0xb1,0x52,0x23,0x56,0x6b,0xc4,0x5b,0xe,0x47,0x42,0x4d,0x4a,0xc,0x5a,0x8f,0xb3,0x16,0xf0,0x97,0x99,0xa7,0x8c,0x99,0xf9,0x1,0xd8,0x7d,0xfe,0x63,0xc6,0x9d,0xf3,0x88,0xbd,0x1d,0x7c,0xe1,0x31,0xc6,0xb8,0x66,0xbc,0x7f,0xbe,0x76,0xbc,0xee,0x6b,0xe8,0xc0,0xa5,0x7a,0xb4,0x8b,0x85,0xec,0xe2,0xea,0x49,0x1c,0x4a,0x6f,0x11,0xe3,0xe9,0xc7,0xad,0xb2,0x8c,0x89,0x68,0x41,0x3c,0x11,0x11,0xcb,0xb8,0xfe,0xd,0xe7,0xc4,0x0,0xbe,0xf0,0x19,0x6e,0x12,0x2e,0x85,0x6a,0x3c,0xe5,0x35,0x34,0xdf,0x3a,0x9a,0x1b,0xb8,0x2f,0x53,0x38,0x79,0x45,0xc9,0x1d,0xba,0x1f,0x58,0xfe,0x52,0xb5,0x1a,0x3,0x1e,0x7e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};
41 |
42 | UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy:bytesIcon length:sizeof(bytesIcon) freeWhenDone:NO]];
43 |
44 | [VZInspector addToolItem:[VZInspectorToolItem itemWithName:@"File Bytes" icon:image callback:^{
45 | NSString *file = [UIPasteboard generalPasteboard].string;
46 | NSData *data;
47 | NSString *message;
48 | if ([file hasPrefix:@"/"]) {
49 | data = [NSData dataWithContentsOfFile:file];
50 | if (data) {
51 | NSUInteger len = [data length];
52 | Byte *bytes = (Byte *)[data bytes];
53 | NSMutableString *str = @"{".mutableCopy;
54 | for (int i=0; i
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 |
--------------------------------------------------------------------------------
/VZInspectorDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/VZInspectorDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/VZInspectorDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 |
7 | @interface ViewController : UIViewController
8 |
9 |
10 | @end
11 |
12 |
--------------------------------------------------------------------------------
/VZInspectorDemo/ViewController.mm:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // VZInspectorDemo
4 | //
5 | // Created by moxin on 9/11/18.
6 | // Copyright © 2018 Tao Xu. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #include
11 |
12 | @interface ViewController()
13 | @property(nonatomic,strong) id list;
14 | @property(nonatomic,strong) UITableView* tableView;
15 | @property(nonatomic,strong) NSMutableArray* items;
16 |
17 | @end
18 |
19 | @implementation ViewController
20 |
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | [self setTitle:@"Inspector Demo"];
26 | self.edgesForExtendedLayout = UIRectEdgeNone;
27 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(load)];
28 | self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(memoryPeek)];
29 |
30 | self.items = [NSMutableArray new];
31 |
32 | self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds)-64)];
33 | self.tableView.delegate = self;
34 | self.tableView.dataSource = self;
35 | [self.view addSubview:self.tableView];
36 | [self load];
37 |
38 |
39 | }
40 |
41 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
42 | {
43 | return 1;
44 | }
45 |
46 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
47 | {
48 | return self.items.count;
49 | }
50 |
51 | - (UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
52 | {
53 | static NSString* identifier = @"vzinspectordemo";
54 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
55 |
56 | if (!cell) {
57 | cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
58 | }
59 |
60 | NSDictionary* info = self.items[indexPath.row];
61 | cell.textLabel.font = [UIFont boldSystemFontOfSize:18.0f];
62 | cell.textLabel.numberOfLines = 0;
63 | cell.textLabel.text = info[@"title"];
64 | [cell.textLabel sizeToFit];
65 |
66 | cell.detailTextLabel.text = info[@"body"];
67 | cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0f];
68 | cell.detailTextLabel.numberOfLines = 0;
69 | [cell.detailTextLabel sizeToFit];
70 |
71 | return cell;
72 |
73 | }
74 |
75 | - (void)load
76 | {
77 | [self.items removeAllObjects];
78 | [self.tableView reloadData];
79 | self.tableView.tableFooterView = [self loadingFooterView];
80 |
81 | NSString* url = @"https://jsonplaceholder.typicode.com/posts/";
82 | [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
83 |
84 | if(data){
85 |
86 | NSDictionary* JSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
87 |
88 | NSLog(@"%@",JSON);
89 |
90 | for (NSDictionary* dict in JSON) {
91 | [self.items addObject:dict];
92 | }
93 | dispatch_async(dispatch_get_main_queue(), ^{
94 |
95 | self.tableView.tableFooterView = nil;
96 | [self.tableView reloadData];
97 |
98 | });
99 | }
100 | else{
101 | dispatch_async(dispatch_get_main_queue(), ^{
102 |
103 | [self alert:@"Error"];
104 | self.tableView.tableFooterView = nil;
105 | });
106 | }
107 |
108 |
109 | }] resume];
110 |
111 | }
112 |
113 | - (void)memoryPeek
114 | {
115 | static int* _ptr = nullptr;
116 | static std::allocator _allocator;
117 | // static std::allocator::size_type sz = 1024*1024*1024*sizeof(int); //this will trigger memory warning
118 | static std::allocator::size_type sz = 1024*1024*sizeof(int);
119 |
120 | if(_ptr){
121 | _allocator.deallocate(_ptr, sz);
122 | _ptr = nullptr;
123 | [self alert:@"Clear"];
124 | }else{
125 | _ptr = _allocator.allocate(sz);
126 | _allocator.construct(_ptr, 0);
127 | NSString* msg = [NSString stringWithFormat:@"Alloc %ld MB memory",sizeof(int)];
128 | [self alert:msg];
129 | }
130 | }
131 | #pragma mark - private method
132 |
133 | - (void)alert:(NSString*) title{
134 | UIAlertView* alert = [[UIAlertView alloc] initWithTitle:title message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
135 | [alert show];
136 | }
137 |
138 |
139 | - (UIView* )loadingFooterView
140 | {
141 | UIView* v = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 44)];
142 | UIActivityIndicatorView* indicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake((CGRectGetWidth(self.view.bounds)-20)/2, 11, 20, 20)];
143 | indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
144 | [indicator startAnimating];
145 | [v addSubview:indicator];
146 |
147 | return v;
148 | }
149 |
150 |
151 | @end
152 |
--------------------------------------------------------------------------------
/VZInspectorDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016年 Vizlab. All rights reserved.
3 | //
4 |
5 | #import
6 | #import "AppDelegate.h"
7 |
8 | int main(int argc, char * argv[]) {
9 | @autoreleasepool {
10 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xta0/VZInspector/506e27b2a7be94651cb020981df50f071f458466/logo.png
--------------------------------------------------------------------------------