前言
在实际开发中,调试程序必不可少,Xcode模拟器与真机调试相比,有时候会有很大区别,因此有时候我们需要在利用真机调试的时候,还能实时的打印log信息,简单的说来就是把显示在控制台中的NSLog信息实时的显示的真机设备上.
思路
首先,收集log信息并不难,下文会有代码和demo供参考.
其次,调试界面的调出应该隐蔽,防止用户调出来影响体验,只有我们程序员知道如何调出来,你可以通过三指下滑调出或者摇一摇调出调试模式,后期测试无bug之后再删除该功能即可.
最后,你调出的调试界面不应该影响你对程序的其他操作,并且该模式可以在任意时刻通过隐藏手势调出来,这就要求该调试界面必须可以挪动,可以放大缩小并且隐藏手势要写到任何地方都能响应的地方,这样就不影响你进行其他页面的操作了.
具体实现过程
对调试模式封装,继承自UIView,上代码
YYLogView.h文件
//
// YYLogView.h
// Log
//
// Created by yyMae on 15/12/23.
// Copyright (c) 2015年 yyMae. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface YYLogView : UIView
//直接初始化 添加到目标父视图即可使用
@end
YYLogView.m文件
//
// YYLogView.m
// Log
//
// Created by yyMae on 15/12/23.
// Copyright (c) 2015年 yyMae. All rights reserved.
// 调试信息可视化(NSLog信息实时显示,可缩放,可挪动)
#import "YYLogView.h"
@interface YYLogView ()<UIGestureRecognizerDelegate>
@property (nonatomic ,strong) UIView *keyView;
@property (nonatomic ,strong) UITextView *logView;
@property (nonatomic ,strong) UIButton *whiteSpotBtn;
@end
@implementation YYLogView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.keyView];
}
return self;
}
-(UIView *)keyView{
if (_keyView==nil) {
self.keyView=[[UIView alloc]initWithFrame:self.bounds];
self.logView=[[UITextView alloc]initWithFrame:CGRectMake(25, 15, self.keyView.frame.size.width-50, self.keyView.frame.size.height-30)];
[self.keyView addSubview:self.logView];
self.keyView.userInteractionEnabled=YES;
self.keyView.backgroundColor=[UIColor brownColor];
self.logView.backgroundColor=[UIColor clearColor];
self.logView.textColor=[UIColor whiteColor];
self.logView.editable=NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *filePath = [docDir stringByAppendingPathComponent:@"dr.log"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.logView.text=result;
[self addGestureRecognizerToView:self];
[self timerAction];
//添加一个可以关闭的按钮
UIButton *closeBtn=[UIButton buttonWithType:UIButtonTypeSystem];
closeBtn.frame=CGRectMake(0, 5, 30, 15);
closeBtn.titleLabel.font=[UIFont systemFontOfSize:15];
[closeBtn setTitle:@"❌" forState:UIControlStateNormal];
[closeBtn addTarget:self action:@selector(closeLoggerView) forControlEvents:UIControlEventTouchUpInside];
[self.keyView addSubview:closeBtn];
}
return _keyView;
}
//==========缩放 移动 =================
// 添加所有的手势
- (void) addGestureRecognizerToView:(UIView *)view
{
// 缩放手势
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchView:)];
[view addGestureRecognizer:pinchGestureRecognizer];
// 移动手势
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panView:)];
[view addGestureRecognizer:panGestureRecognizer];
}
// 处理缩放手势
- (void) pinchView:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
UIView *view = pinchGestureRecognizer.view;
if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan || pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) {
view.transform = CGAffineTransformScale(view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);
pinchGestureRecognizer.scale = 1;
}
}
// 处理拖拉手势
- (void) panView:(UIPanGestureRecognizer *)panGestureRecognizer
{
UIView *view = panGestureRecognizer.view;
if (panGestureRecognizer.state == UIGestureRecognizerStateBegan || panGestureRecognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [panGestureRecognizer translationInView:view.superview];
[view setCenter:(CGPoint){view.center.x + translation.x, view.center.y + translation.y}];
[panGestureRecognizer setTranslation:CGPointZero inView:view.superview];
}
}
- (void)timerAction{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(readd) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
}
-(void)readd{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *filePath = [docDir stringByAppendingPathComponent:@"dr.log"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.logView.text = result;
}
//关闭
-(void)closeLoggerView{
[self removeFromSuperview];
}
@end
AppDelegate.m中收集NSLog信息,并且通过摇一摇手势调出调试界面
//
// AppDelegate.m
// Log
//
// Created by yyMae on 15/12/15.
// Copyright (c) 2015年 yyMae. All rights reserved.
//
#import "AppDelegate.h"
#import "YYLogView.h"
@interface AppDelegate ()<UIGestureRecognizerDelegate>
@property (nonatomic,strong) YYLogView *loggerView;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self saveLog];
self.loggerView=[[YYLogView alloc]initWithFrame:CGRectMake(10, 80, self.window.frame.size.width-20, 200)];
NSLog(@"调试信息可视化");
NSLog(@"输出");
return YES;
}
-(void)saveLog{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *document = [path objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:@"dr.log"];
NSString *logPath = [document stringByAppendingPathComponent:fileName];
NSFileManager *defaulManager = [NSFileManager defaultManager];
[defaulManager removeItemAtPath:logPath error:nil];
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}
////摇一摇
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
[[[UIApplication sharedApplication]keyWindow]addSubview:self.loggerView];
}
}
@end
需要学习的可以看下我写的demo
github地址:https://github.com/yyMae/Log-