iOS 收集打印日志

可以将要在Xcode 控制台打印的日志写在沙盒,最后导出分享,进行问题分析。

正式版本不建议使用,避免增加用户内存。配合解决顽固 Bug 可以通过该方法收集打印日志

.h头文件

Objective-C 复制代码
@interface LogManager : NSObject
+ (FSLogManager *)shareInstance;
- (void)redirectNSlogToDocumentFolder;
- (NSString *)logDirPath;
- (void)clearAllLog;
- (float)sizeOfLogs;
@end

.m实现文件

Objective-C 复制代码
#import "LogManager.h"
#import <UIKit/UIKit.h>

#define LOG_TIME_FORMAT @"yyyy-MM-dd HH:mm:ss.SSS"
#define LOG_QUEUE_ID "log_queue"

static LogManager *manager = nil;

/// 是否运行收集日志,如果为 YES , 将不会在日志控制台打印。
static BOOL const kAllowSaveLog = YES;

@implementation LogManager
+ (LogManager *)shareInstance{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[LogManager alloc] init];
        if (kAllowSaveLog) {
            [self setDefaultUncaughtExceptionHandler];
        }
    });
    return manager;
}
- (void)clearAllLog {
    NSArray<NSString *> *allPath = [self allLogPath];
    if (allPath.count == 0) {
        return;
    }
    [allPath enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSError *error;
         [[NSFileManager defaultManager] removeItemAtPath:obj error:&error];
    }];
}
- (void)redirectNSlogToDocumentFolder{
    if (kAllowSaveLog == NO) {
        return;
    }
    UIDevice *device = [UIDevice currentDevice];
    if ([[device model] isEqualToString:@"Simulator"]) {
        return;
    }

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *dateString = [formatter stringFromDate:[NSDate date]];

    NSString *documentDirectory = [self logDirPath];
    NSString *fileName = [NSString stringWithFormat:@"%@-log.txt",dateString];
    NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:fileName];

    // Delete existing files
    [[NSFileManager defaultManager] removeItemAtPath:logFilePath error:nil];

    //Enter the log into the file  (所有的打印都会存在该文件)
    freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding], "a+", stdout);
    freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);

}

- (float)sizeOfLogs{
    NSDirectoryEnumerator *direnum = [[NSFileManager defaultManager] enumeratorAtPath:[self logDirPath]];
    NSString *pname;
    int64_t s=0;
    while (pname = [direnum nextObject]){
        NSDictionary *currentdict=[direnum fileAttributes];
        NSString *filesize=[NSString stringWithFormat:@"%@",[currentdict objectForKey:NSFileSize]];
        NSString *filetype=[currentdict objectForKey:NSFileType];
        
        if([filetype isEqualToString:NSFileTypeDirectory]) continue;
        s=s+[filesize longLongValue];
    }
    return s*1.0;
}
- (NSString *)logDirPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [paths objectAtIndex:0];
    NSString *logPath = [documentDirectory stringByAppendingPathComponent:@"Logs"];
    BOOL isDir = NO;
    BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:logPath isDirectory:&isDir];
    if (isExist && isDir) {
        
    } else {
        NSError * createDirError;
        [[NSFileManager defaultManager] createDirectoryAtPath:logPath withIntermediateDirectories:YES attributes:nil error:&createDirError];
    }
    return logPath;
}
- (NSArray<NSString *> *)allLogPath {
 NSArray<NSString *> *items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self logDirPath] error:nil];
    NSMutableArray<NSString *> *paths = [NSMutableArray array];
    NSString *dirPath = [self logDirPath];
    [items enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [paths addObject:[dirPath stringByAppendingPathComponent:obj]];
    }];
    return paths;
}

#pragma mark -设置crash
+ (void)setDefaultUncaughtExceptionHandler
{
 
    NSSetUncaughtExceptionHandler (&chUncaughtExceptionHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGFPE, SignalHandler);
    signal(SIGBUS, SignalHandler);
    signal(SIGPIPE, SignalHandler);
    
}
 
#pragma mark -获取崩溃日志
void chUncaughtExceptionHandler(NSException *exception)
{
    NSLog(@"Exception info --> %@",exception);
}
 
void SignalHandler(int signal)
{
    //拦截signal
}

@end

分享

收集到的日志可以通过云端上传,也可以直接通过系统原生分享。

Objective-C 复制代码
/// items 可以传文件路径path。 
+ (void)shareItems:(NSArray *)items  fromController:(UIViewController *)controller cancel:(void(^)(void))cancel completion:(void(^)(NSError * _Nullable error))completion {
    if (items.count == 0) {
        return;
    }
    //初始化:
    UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
    activityVC.completionWithItemsHandler = ^(UIActivityType  _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
        // 如果取消, completed返回 NO
        if (completed) {
            if (completion) {
                completion(activityError);
            }
        } else {
            if (cancel) {
                cancel();
            }
        }
    };
    //禁掉不用的服务
    activityVC.excludedActivityTypes = @[UIActivityTypePrint,UIActivityTypeAssignToContact];
    [controller presentViewController:activityVC animated:YES completion:nil];
}
相关推荐
他们都不看好你,偏偏你最不争气5 小时前
AutoLayout与Masonry:简化iOS布局
ios
2501_916008898 小时前
iOS 抓包工具有哪些?全面盘点主流工具与功能对比分析
android·ios·小程序·https·uni-app·iphone·webview
2501_915921438 小时前
iOS混淆工具实战 视频流媒体类 App 的版权与播放安全保护
android·ios·小程序·https·uni-app·iphone·webview
2501_9160088912 小时前
uni-app iOS 日志与崩溃分析全流程 多工具协作的实战指南
android·ios·小程序·https·uni-app·iphone·webview
2501_9159214313 小时前
iOS混淆工具实战 在线教育直播类 App 的课程与互动安全防护
android·安全·ios·小程序·uni-app·iphone·webview
Digitally15 小时前
没 iCloud, 如何数据从iPhone转移到iPhone
ios·iphone·icloud
笑尘pyrotechnic15 小时前
push pop 和 present dismiss
macos·ui·ios·objective-c·cocoa
Digitally16 小时前
如何将联系人从 iPhone 转移到 Redmi 手机
ios·智能手机·iphone
2501_9151063217 小时前
Charles抓包工具在接口性能优化与压力测试中的实用方法
ios·性能优化·小程序·https·uni-app·压力测试·webview
Winson℡1 天前
在 React Native 层禁止 iOS 左滑返回(手势返回/手势退出)
react native·react.js·ios