級別:★☆☆☆☆
標籤:「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
奇舞週刊