一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
此框架只能捕获基础类型(详细看注意事项)导致的崩溃,捕获之后不会闪退,也不会上报bugly,但是bug需要自己排查,所以上传崩溃日志到企业微信并@相应开发人员查看。
集成AvoidCrash
pod 'AvoidCrash', '~> 2.5.2'
在AppDelegate的application:didfinish里添加
[AvoidCrash makeAllEffective];
[AvoidCrash setupNoneSelClassStringsArr:@[@``"NSString"``, @``"NSNull"``, @``"NSNumber"``, @``"NSDictionary"``, @``"NSArray"``]];
[[NSNotificationCenter defaultCenter]addObserver:self selector:``@selector``(dealwithCrashMessage:) name:AvoidCrashNotification object:nil];
- (void)dealwithCrashMessage:(NSNotification *)note {
//注意:所有的信息都在userInfo中
//你可以在这里收集相应的崩溃信息进行相应的处理(比如传到自己服务器)
NSDictionary *info = note.userInfo;
/// 上报企业微信
[JXWechatBotRequest uploadCrashInfo:info];
}
JXWechatBotRequest这个类实现上报企业微信机器人@相应开发人员
- (instancetype)initWithText:(NSString *)text {
self = [super init];
if (self) {
/// 自己替换企业微信名称和手机号
self.params = @{@"msgtype":@"text",
@"text":@{
@"content":text,
@"mentioned_list":@[@""],
@"mentioned_mobile_list":@[@""]
}
};
}
return self;
}
- (NSString *)requestUrl {
///替换成自己的webhook链接
return @"";
}
- (YTKRequestMethod)requestMethod {
return YTKRequestMethodPOST;
}
- (id)requestArgument {
return self.params;
}
- (YTKRequestSerializerType)requestSerializerType {
return YTKRequestSerializerTypeJSON;
}
- (YTKResponseSerializerType)responseSerializerType {
return YTKResponseSerializerTypeHTTP;
}
/// 打包日志
+ (void)uploadDDLogInfo:(void(^)(NSString *url))completeBlock {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData *zipData = [JXCocoaZipManager jxCompressedFileWithLogs];
if (zipData) {
[[JXBKUpload shareManager]aliyunUploadSingleFile:zipData suffix:@"zip" progress:^(int64_t progressBytes, int64_t totalProgressBytes) {
} success:^(BOOL success, NSString *url) {
dispatch_async_on_main_queue(^{
if (completeBlock) {
completeBlock(url);
}
});
}];
} else {
dispatch_async_on_main_queue(^{
if (completeBlock) {
completeBlock(nil);
}
});
}
});
}
+ (void)uploadCrashInfo:(NSDictionary *)info {
[self uploadDDLogInfo:^(NSString *url) {
NSArray *callStack = info[@"callStackSymbols"];
NSDictionary *extraInfo = @{@"currentControllers":[JXBKRouter getCurrentVC].navigationController.viewControllers};
NSString *errorReason = [NSString stringWithFormat:@"【ErrorReason】%@\n【ErrorPlace】%@\n【DefaultToDo】%@\n【ErrorName】%@\n【extraInfo】%@", info[@"errorReason"], info[@"errorPlace"], info[@"defaultToDo"], info[@"errorName"], extraInfo];
DDLogInfo(@"***crash***:%@", [NSThread currentThread]);
DDLogInfo(@"***crash***:%@", errorReason);
DDLogInfo(@"***crash***:%@", callStack);
NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
NSString *deviceModel = [[UIDevice currentDevice] model];
NSString *env;
#ifdef DEBUG
env = @"Debug";
#else
env = @"Release";
#endif
NSString *content = [NSString stringWithFormat:@"%@\n【日志】%@\n【设备型号】%@-%@\n【环境】%@", errorReason, url, deviceModel, sysVersion, env];
JXWechatBotRequest *request = [[JXWechatBotRequest alloc]initWithText:content];
[request startWithCompletionBlockWithSuccess:^(__kindof YTKBaseRequest * _Nonnull request) {
} failure:^(__kindof YTKBaseRequest * _Nonnull request) {
}];
}];
}
注意事项
这个框架的适用范围是下表,像OOM、APP卡死等无法捕获
| 类名 | 适用范围 |
|---|---|
| 类名 | 适用范围 |
| NSString | 1. - (unichar)characterAtIndex:(NSUInteger)index2. - (NSString *)substringFromIndex:(NSUInteger)from3. - (NSString *)substringToIndex:(NSUInteger)to {4. - (NSString *)substringWithRange:(NSRange)range {5. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement6. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange7. - (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement |
| NSMutableString | 1. 由于NSMutableString是继承于NSString,所以这里和NSString有些同样的方法就不重复写了2. - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString3. - (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc4. - (void)deleteCharactersInRange:(NSRange)range |
| NSMutableDictionary | 1. - (void)setObject:(id)anObject forKey:(id)aKey2. - (void)removeObjectForKey:(id)aKey |
| NSMutableAttributedString | 1.- (instancetype)initWithString:(NSString *)str2.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs |
| NSMutableArray | 1. - (id)objectAtIndex:(NSUInteger)index2. - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx3. - (void)removeObjectAtIndex:(NSUInteger)index4. - (void)insertObject:(id)anObject atIndex:(NSUInteger)index5. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range |
| NSDictionary | 1. NSDictionary的快速创建方式 NSDictionary *dict = @{@"frameWork" : @"AvoidCrash"}; //这种创建方式其实调用的是2中的方法2. +(instancetype)dictionaryWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt |
| NSAttributedString | 1.- (instancetype)initWithString:(NSString *)str2.- (instancetype)initWithAttributedString:(NSAttributedString *)attrStr3.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs |
| NSArray | 1. NSArray的快速创建方式 NSArray *array = @[@"chenfanfang", @"AvoidCrash"]; //这种创建方式其实调用的是2中的方法2. +(instancetype)arrayWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt3. - (id)objectAtIndex:(NSUInteger)index4. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range |