级别:★☆☆☆☆
标签:「iOS 查看及导出项目运行日志」「iOS 查看日志」「iOS 查看崩溃日志」
做者: WYW
审校: QiShare团队php
前文:
最近笔者在家远程办公的时候,在测试项目时,遇到了测试同窗测试出了问题,可是笔者这边不能复现的状况。因此整理了一下 iOS 查看及导出项目运行日志。如你们有须要,能够继续查看详情。html
笔者将分享iOS 查看及导出项目运行日志的内容,全文分为以下7个部分。git
iPhone 链接 Mac 的状况下使用控制台, 搜索项目名称,笔者这里的项目名称为 QiLogTool ,找出相应的日志。此时无论是否正在使用 Xcode 在运行项目,在控制台中都能查看到 iPhone 中的日志。github
注:NSLog 重定向后,控制台就不会打印日志了。数组
使用以下代码能够把 NSLog 日志,重定向到指定的文件目录中。bash
+ (void)redirectNSLog {
NSString *fileName = @"NSLog.log";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = paths.firstObject;
NSString *saveFilePath = [documentDirectory stringByAppendingPathComponent:fileName];
// 先删除已经存在的文件
NSFileManager *defaultManager = [NSFileManager defaultManager];
[defaultManager removeItemAtPath:saveFilePath error:nil];
// 将log输入到文件
freopen([saveFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen([saveFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}
复制代码
freopen是被包含于C标准库头文件<stdio.h>中的一个函数,用于重定向输入输出流。该函数能够在不改变代码原貌的状况下改变输入输出环境,但使用时应当保证流是可靠的。微信
引自360百科:freopenapp
FILE *freopen( const char * __restrict, const char * __restrict, FILE * __restrict) __DARWIN_ALIAS(freopen);
形参说明:
filename:须要重定向到的文件名或文件路径。
mode:表明文件访问权限的字符串。例如,"r"表示"只读访问"、"w"表示"只写访问"、"a"表示"追加写入"。
stream:须要被重定向的文件流。
复制代码
下图是笔者把 NSLog 的内容重定向输出到 NSLog.log 以后的截图。ide
下图是笔者在官方文档截图的沙盒目录。函数
下方的截图依次是笔者经过 Xcode 获取安装包中的沙盒文件的截图。
使用 PAirSandbox:AirSandbox,从手机屏幕右侧边缘,左滑手势能够触发显示查看当前沙盒中的内容的window。而且能够经过三方软件把沙盒中的内容分享给其余人。点击右上角的 Close 关闭按钮便可关闭沙盒目录界面。
#ifdef DEBUG
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[PAirSandbox sharedInstance] enableSwipe];
});
#endif
复制代码
效果示意图以下:
须要在 Info.plist 文件中配置以下内容,即可实时在文件 App 中查看沙盒中的文件内容。
设置 Application supports iTunes file sharing
为YES。 设置 Supports opening documents in place
为 YES。
设置的示意图以下:
经过文件 App 实时查看日志的效果示意图以下。
/** * 普通异常的捕获方式: * 2020-03-25 10:47:11.179085+0800 QiLogTool[18371:4064396] exception:*** * -[__NSSingleObjectArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 0] * 2020-03-25 10:47:11.179310+0800 QiLogTool[18371:4064396] finally */
@try {
NSArray *arr = @[@(1)];
arr[2];
} @catch (NSException *exception) {
NSLog(@"exception:%@", exception);
} @finally {
NSLog(@"finally");
}
复制代码
若是项目中可能出现异常的地方比较多,使用try catch的方式可能会比较繁琐。那么能够考虑使用捕获项目全局异常的方式。
下方的代码能够查看异常状况,而且记录下来日志,在用户侧,可实现可把崩溃日志上传到服务端,进行日志分析的操做。不过 App 遇到异常依然会闪退。
#ifdef DEBUG
// 捕获异常 Summary Changes the top-level error handler.
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
#endif
复制代码
#pragma mark - 捕获异常 不防崩
void UncaughtExceptionHandler(NSException *exception) {
// 获取异常崩溃信息
NSArray *callStack = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *crashDetail = [NSString stringWithFormat:@"========异常错误报告========\n name:%@\n reason:\n%@\n callStackSymbols:\n%@", name, reason, [callStack componentsJoinedByString:@"\n"]];
NSLog(@"%@", crashDetail);
[QiLogTool logFile:@"crash.log" content:crashDetail];
}
复制代码
首先感谢 RunLoop总结:RunLoop的应用场景(五)
QiLogTool 中也有相关的代码。你们有兴趣的话,能够自行下载查看。
捕获异常部分的代码,和笔者在上文中第2步中提到的全局捕获异常的方式相似。能够多了解一下的还有,出现了异常的状况下,咱们能够记录日志,而且使用 RunLoop 相关代码保持应用在第一次遇到异常的时候不崩溃。
RunLoop处理遇到异常,保持App 仍然能够继续运行一次的主要代码为:
// 获取到当前线程的的CFRunLoop对象及 获取包含特定CFRunLoop对象的Modes数组 在指定的Modes中运行当前线程的CFRunLoop对象
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!ignore) {
for (NSString *mode in (__bridge NSArray *)allModes) {
// Runs the current thread’s CFRunLoop object in a particular mode.
CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
}
}
CFRelease(allModes);
复制代码
经过以下方式查看崩溃日志不许确。
~/Library/Logs/CrashReporter/MobileDevice
复制代码
上边的红色箭头的1,2能够用于查看设备端经过 Xcode 安装的项目的日志;
下边的蓝色箭头的1,2能够用于查看上传到 AppStore 项目的 Crash 的日志。
把 CrashHandler 和 AirSandBox 及 QiLogTool 的文件夹中的文件都添加到本身的项目中。 在应用启动的时候调用以下代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (@available(iOS 13.0, *)) {
} else {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]];
[self.window makeKeyAndVisible];
}
// 是否要直接访问沙盒中的内容
#ifdef DEBUG
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[PAirSandbox sharedInstance] enableSwipe];
});
#endif
// 重定向NSLog内容 注意:把NSLog的内容重定向到其余文件后 控制台就不会再输出内容
[QiLogTool redirectNSLog];
#ifdef DEBUG
// 捕获异常 Changes the top-level error handler.
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
#endif
// #ifdef DEBUG
#ifdef RELEASE
// 捕获异常而且有一次应用遇到异常后 不会闪退的处理
[CrashHandler sharedInstance];
#endif
return YES;
}
复制代码
#pragma mark - 捕获异常 不防崩
void UncaughtExceptionHandler(NSException *exception) {
// 获取异常崩溃信息
NSArray *callStack = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *crashDetail = [NSString stringWithFormat:@"========异常错误报告========\n name:%@\n reason:\n%@\n callStackSymbols:\n%@", name, reason, [callStack componentsJoinedByString:@"\n"]];
NSLog(@"%@", crashDetail);
[QiLogTool logFile:@"crash.log" content:crashDetail];
// 记录日志后 能够选择合适的时机把日志上传到服务端 上传成功后 把相应的日志删除便可
}
复制代码
笔者下边的演示在应用启动时调用的代码为:
// 是否要直接访问沙盒中的内容
#ifdef DEBUG
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[PAirSandbox sharedInstance] enableSwipe];
});
#endif
// 重定向NSLog内容 注意:把NSLog的内容重定向到其余文件后 控制台就不会再输出内容
[QiLogTool redirectNSLog];
#ifdef DEBUG
// #ifdef RELEASE
// 捕获异常而且有一次应用遇到异常后 不会闪退的处理
[CrashHandler sharedInstance];
#endif
复制代码
下图中点击屏幕中间的测试日志按钮后,会调用的方法以下:
- (void)logTest {
NSLog(@"NSLog日志内容");
// 测试日志工具
[QiLogTool logFile:@"logfile.log" content:[NSString stringWithFormat:@"时间:%@\n内容:%@\n", [[NSDate date] dateByAddingTimeInterval:8.0 * 60 * 60], @"logContent"]];
// 测试崩溃 记录日志效果
NSArray *arr = @[@(1)];
NSLog(@"arr[2]:%@", arr[2]);
}
复制代码
因笔者录制的 gif 图较大,直接上传受限。如需查看使用过程当中的效果图可点击下方连接 QiLogTool使用效果图
File System Programming Guide
iOS 将NSLog日志重定向输出到文件中保存
iOS崩溃异常的处理
RunLoop总结:RunLoop的应用场景(五)
了解更多iOS及相关新技术,请关注咱们的公众号:
小编微信:可加并拉入《QiShare技术交流群》。
关注咱们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)
推荐文章:
Flutter Platform Channel 使用与源码分析
开发没切图怎么办?矢量图标(iconFont)上手指南
DarkMode、WKWebView、苹果登陆是否必须适配?
iOS 接入 Google、Facebook 登陆(二)
iOS 接入 Google、Facebook 登陆(一)
Nginx 入门实战 iOS中的3D变换(二)
iOS中的3D变换(一)
WebSocket 双端实践(iOS/ Golang)
今天咱们来聊一聊WebSocket(iOS/Golang)
奇舞团安卓团队——aTaller
奇舞周刊