一般在開(kāi)發(fā)中,我們查看線上的崩潰信息,都會(huì)集成友盟,騰訊bugly等第三方SDK,這些SDK 可能帶來(lái)的問(wèn)題就是并非每一個(gè)都會(huì)記錄到,而且不及時(shí)。
蘋(píng)果自身有一個(gè)函數(shù),只要發(fā)生了崩潰,這個(gè)函數(shù)就會(huì)被調(diào)用,我們通過(guò)這個(gè)函數(shù)就可以吧 捕獲到的crash信息存入本地,并上傳到服務(wù)器,這樣可以及時(shí)查看,并且可以針對(duì)性的加入我們需要上傳的額外信息,比如具體用戶(hù)等等。
代碼實(shí)現(xiàn):
創(chuàng)建ZYKCrashHandler類(lèi)
//在ZYKCrashHandler.h中
#import <Foundation/Foundation.h>
#define UncaughtExceptionManager [ZYKCrashHandler shareInstance]
@interface ZYKCrashHandler : NSObject
+ (instancetype)shareInstance;
- (void)setDefaultHandler;
- (void)collectionExceptionMessage;
- (NSUncaughtExceptionHandler *)getHandler;
//在ZYKCrashHandler.m中實(shí)現(xiàn)方法
/ 沙盒的地址
NSString * applicationDocumentsDirectory() {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
// 崩潰時(shí)的回調(diào)函數(shù)
void UncaughtExceptionHandler(NSException * exception) {
NSArray *stackSymbols = [exception callStackSymbols];
NSString *reason = [exception reason];//原因
NSString *name = [exception name];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy:MM:dd:HH:mm:ss"];
NSString *time = [dateFormatter stringFromDate:[NSDate date]]; //時(shí)間
NSString *exceptionInfo = [NSString stringWithFormat:@"====異常報(bào)告====%@\nException name:%@\nException reason:%@\nException stackSymbols :\n%@",time,name,reason,[stackSymbols componentsJoinedByString:@"\n"]];
NSLog(@"%@",exceptionInfo);
NSString * path = [applicationDocumentsDirectory() stringByAppendingPathComponent:@"Exception.txt"];
// 將一個(gè)txt文件寫(xiě)入沙盒
[exceptionInfo writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
@implementation ZYKCrashHandler
+ (instancetype)shareInstance {
static ZYKCrashHandler *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[ZYKCrashHandler alloc]init];
});
return instance;
}
- (void)setDefaultHandler {
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
[self collectionExceptionMessage];
}
// 獲取崩潰統(tǒng)計(jì)的函數(shù)指針
- (NSUncaughtExceptionHandler *)getHandler {
return NSGetUncaughtExceptionHandler();
}
- (void)collectionExceptionMessage {
// 發(fā)送崩潰日志
NSString *dataPath = [applicationDocumentsDirectory() stringByAppendingPathComponent:@"Exception.txt"];
NSData *data = [NSData dataWithContentsOfFile:dataPath];
if (data != nil) {
[self sendExceptionLogWithData:data path:dataPath];
}
}
#pragma mark -- 發(fā)送崩潰日志
- (void)sendExceptionLogWithData:(NSData *)data path:(NSString *)path {
// AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// manager.requestSerializer.timeoutInterval = 10.0f;
// //告訴AFN,接受 text/xml 的數(shù)據(jù)
// [AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/plain"];
// NSString *urlString = @"后臺(tái)地址";
// [manager POST:urlString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
// [formData appendPartWithFileData:data name:@"file" fileName:@"Exception.txt" mimeType:@"txt"];
// } progress:^(NSProgress * _Nonnull uploadProgress) {
//
// } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// // 刪除文件
// NSFileManager *fileManger = [NSFileManager defaultManager];
// [fileManger removeItemAtPath:path error:nil];
// } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// // 發(fā)送Bug失敗
// }];
}
//在AppDelegate中導(dǎo)入頭文件調(diào)用即可
//崩潰收集
[UncaughtExceptionManager setDefaultHandler];
開(kāi)發(fā)測(cè)試過(guò)程中,你可以把崩潰信息展示到textview上,方便查看,上線時(shí),你可以把此文件上傳至服務(wù)器。