一. 为何要做这个工具(why make this tool)
因为手动操作很繁杂,如果做成app,一键解析崩溃文件,那就会相当nice
app: 工具在这里下载:链接: pan.baidu.com/s/1gMbrW8ry… 提取码: h4bg
解析崩溃前提知识储备:
使用symbolicatecrash解析了一个crash log
Mac开发需要的知识储备:
你也可以直接忽略,直接开干
首先创建一个mac-应用
监控推入的文件和获取文件
此类功能就是监控推入的文件路径
#import <Cocoa/Cocoa.h>
@protocol DragDropViewDelegate;
@interface DragDropView : NSView
@property (assign) id<DragDropViewDelegate> delegate;
@end
@protocol DragDropViewDelegate <NSObject>
-(void)dragDropViewFileList:(NSArray)fileList;
@end
#import "DragDropView.h"
@implementation** DragDropView
@synthesize delegate = _delegate;
- (id)initWithFrame:(NSRect)frame{
self = [super initWithFrame:frame];
if (self) {
//这里我们只添加对文件进行监听,如果拖动其他数据类型到view中是不会被接受的
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
}
return self;
}
- (instancetype)init{
self = [super init];
if (self) {
//这里我们只添加对文件进行监听,如果拖动其他数据类型到view中是不会被接受的
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, **nil**]];
}
return self;
}
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
return NSDragOperationCopy;
}
return NSDragOperationNone;
}
-(BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender{
// 1)、获取拖动数据中的粘贴板
NSPasteboard *zPasteboard = [sender draggingPasteboard];
// 2)、从粘贴板中提取我们想要的NSFilenamesPboardType数据,这里获取到的是一个文件链接的数组,里面保存的是所有拖动进来的文件地址,如果你只想处理一个文件,那么只需要从数组中提取一个路径就可以了。
NSArray *list = [zPasteboard propertyListForType:NSFilenamesPboardType];
// 3)、将接受到的文件链接数组通过代理传送
if(self.delegate && [self.delegate respondsToSelector: @selector**(dragDropViewFileList:)])
[self.delegate dragDropViewFileList:list];
return YES;
}
- (void)drawRect:(NSRect)dirtyRect{
Drawing code here.
}
- (**void**)dealloc {
[self setDelegate:nil];
}
@end
运用NSTask打开symbolicatecrash应用,并执行解析崩溃
- (void)windowDidLoad{
[super windowDidLoad];
[self setUpView];
}
- (void)setUpView{
[self.dragDropView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
[self.dragDropView setDelegate:self];
}
-(void)dragDropViewFileList:(NSArray *)fileList{
// NSLog(@"%@",fileList);
self.crashFilePath = nil;
self.dsymlFilePath = nil;
[self.logOutView setString:NSLocalizedString(@"defaultTitle", nil)];
for (NSString* filePath in fileList) {
if ([filePath rangeOfString:@".ips"].length > 0 ){
self.crashFilePath = filePath;
}
if([filePath rangeOfString:@"dSYM"].length > 0){
self.dsymlFilePath = filePath;
}
}
if (self.crashFilePath == nil && self.crashFilePath.length <= 0){
[self AlertViewShowWithMessageText:NSLocalizedString(@"warning", @"") InforMativeText:NSLocalizedString(@"nofile", @"")];
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginToAnalysisCrashFile];
});
//获取文件目录,开始解析
}
-(void)beginToAnalysisCrashFile{
NSPipe *pipe = [NSPipe pipe];
NSFileHandle *file = pipe.fileHandleForReading;
NSTask *analysisTask = [[NSTask alloc] init];
NSString *launchPath = @"/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash";
if (launchPath==nil||!([launchPath rangeOfString:@"Xcode.app"].length>0)){
[self AlertViewShowWithMessageText:NSLocalizedString(@"warning", @"") InforMativeText:NSLocalizedString(@"noXcode", @"") ];
}else{
analysisTask.launchPath = launchPath;
}
NSArray *array = [NSArray arrayWithObjects:self.crashFilePath, self.dsymlFilePath, nil];
[analysisTask setArguments:array];
[analysisTask setEnvironment:@{
@"DEVELOPER_DIR":@"/Applications/Xcode.app/Contents/Developer"
}];
[analysisTask setStandardOutput:pipe];
[analysisTask launch];
NSData *data = [file readDataToEndOfFile];
[file closeFile];
NSString *LogOutput = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
}
// _LogOut=[_LogOut stringByAppendingString:[NSString stringWithFormat:@"\n%@",LogOutput]];
[self writeToFileWithContent:LogOutput];
}
-(void)writeToFileWithContent:(NSString*)logOut{
NSString *logoutFilePath = [[self.crashFilePath stringByDeletingPathExtension] stringByAppendingPathExtension:@"log"];
NSError *error;
[logOut writeToFile:logoutFilePath atomically:**YES** encoding:NSUTF8StringEncoding error:&error];
if (error){
dispatch_async(dispatch_get_main_queue(), ^{
[self AlertViewShowWithMessageText:NSLocalizedString(@"alert", @"") InforMativeText:NSLocalizedString(@"errorWriteLog", @"")];
});
}
}
-(void)AlertViewShowWithMessageText:(NSString *)message InforMativeText:(NSString*)info{
NSAlert *alert=[NSAlert alertWithMessageText:message defaultButton:NSLocalizedString(@"confirm",@"") alternateButton:NSLocalizedString(@"cancel",@"") otherButton:nil informativeTextWithFormat: info,nil];
[alert beginSheetModalForWindow:[NSApplication sharedApplication].keyWindow completionHandler:nil];
}