- Log日志的写入本地。
///----------------------------------
/// @name 调试输出
///----------------------------------
#import "_pragma_push.h"
#import
#define DLogOut( ... ) if([DLFrameDebug sharedInstance].enabled)\
[[DLFrameDebug sharedInstance] file:@(__FILE__) line:__LINE__ func:@(__PRETTY_FUNCTION__) format:__VA_ARGS__];
@interface DLFrameDebug : NSObject
@singleton(DLFrameDebug)
/*!
* 是否打开log
*/
@prop_assign(BOOL, enabled)
/// LogLevel, without in this framework
- (void)file:(NSString *)file line:(NSUInteger)line func:(NSString *)func format:(NSString *)format, ...;
@end
#import "_pragma_pop.h"
#import "DLFrameDebug.h"
@implementation DLFrameDebug
@def_singleton(DLFrameDebug)
- (void)file:(NSString *)file line:(NSUInteger)line func:(NSString *)func format:(NSString *)format, ... {
if ( nil == format || NO == [format isKindOfClass:[NSString class]] )
return;
va_list args;
va_start( args, format );
[self file:file line:line func:func format:format args:args];
va_end( args );
}
- (void)file:(NSString *)file line:(NSUInteger)line func:(NSString *)func format:(NSString *)format args:(va_list)params {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
@autoreleasepool {
NSMutableString * content = [[NSMutableString alloc] initWithFormat:(NSString *)format arguments:params];
if ( content && content.length )
{
NSMutableString * text = [[NSMutableString alloc] init];
if ( text ) {
[text appendString:content];
if ( [text rangeOfString:@"%"].length )
{
[text replaceOccurrencesOfString:@"%"
withString:@"%%"
options:NSLiteralSearch
range:NSMakeRange(0, text.length)];
}
if (![[NSFileManager defaultManager] fileExistsAtPath:DL_LOG_PATH]) {
[[NSFileManager defaultManager] createFileAtPath:DL_LOG_PATH contents:nil attributes:nil];
}
NSString * logStr = [NSString stringWithContentsOfFile:DL_LOG_PATH encoding:NSUTF8StringEncoding error:nil];
if (logStr) {
logStr = [logStr stringByAppendingFormat:@"\n\n[TIME]:%@\n[FILE]:%@\n[FUNC]:%@\n[LINE]:%ld\n----->\n[INFO]:\n%@\n<-----\n", [NSDate date], file, func, (unsigned long)line, text];
} else {
logStr = text;
}
[logStr writeToFile:DL_LOG_PATH atomically:YES encoding:NSUTF8StringEncoding error:nil];
fprintf( stderr, "\n\n--->\n[TIME]:%s\n[FUNC]:%s\n[LINE]:%d\n[INFO]:\n%s\n<---\n\n", [NSString stringWithFormat:@"%@", [NSDate date]].UTF8String, func.UTF8String, line, [text UTF8String]);
}
}
}
}
@end
这样, 我们完成了Log日志的本地写入, 上边这种方法只是最普通的办法, 原本打算使用FILE然后重指向stderr的, 嘿嘿想想还是算了。 俗气的才是高大上的。 直接writetofile。
- Exception的捕获。
在ApplicationDidFinishLaunch中, 设置异常捕获的方法
if ([DLFrameDebug sharedInstance].enabled) {
// Add Exception Handler
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
}
并实现这个方法, 使用Log把异常Log到日志中
void UncaughtExceptionHandler(NSException *exception) {
NSArray *callStack = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *content = [NSString stringWithFormat:@"\n异常错误报告\nname:%@\nreason:\n%@\ncallStackSymbols:\n%@",name,reason,[callStack componentsJoinedByString:@"\n"]];
DLogOut(@"%@", content);
}
- 是否正常退出
我专门写了一个Manager的单例类, 用来管理这个,要注册响应的应用程序状态的通知.
// Add Notification For Default Manager
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(UIApplicationDidFinishLaunchingNotification)
name:UIApplicationDidFinishLaunchingNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(UIApplicationDidEndBackgroundNotification)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(UIApplicationDidBecameActive)
name:UIApplicationDidBecomeActiveNotification
object:nil];
在程序退到后台的时候, 设置一下正确退出了、 进入前台的时候设置不正确退出。 这样的话, 程序非正常退出的时候判断一下bool值就可以了。 在上次正常的情况下清理Log文件, 如果没有正常退出那就发送信息到服务器, 并清空。
- (void)UIApplicationDidFinishLaunchingNotification {
// start some application operations
[self startUp];
}
- (void)UIApplicationDidEndBackgroundNotification {
// Change the Application Exit Status
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:ApplicationExited];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)UIApplicationDidBecameActive {
// check application exit normal
[self checkApplicationExitedNormal];
// set first launch
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:ApplicationFirstLaunch];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)checkApplicationExitedNormal {
NSLog(@"%d", [NSUserDefaults boolForKey:ApplicationExited]);
if (![NSUserDefaults boolForKey:ApplicationExited] && ![NSUserDefaults boolForKey:ApplicationFirstLaunch]) {
// Application first launch
} else if ([NSUserDefaults boolForKey:ApplicationFirstLaunch] && ![NSUserDefaults boolForKey:ApplicationExited]) {
NSString * logStr = [NSString stringWithContentsOfFile:DL_LOG_PATH encoding:NSUTF8StringEncoding error:nil];
if (logStr) {
[DLServer POST:@"logs.api" param:[@{
@"data" : logStr
} mutableCopy] complete:^(BOOL requestSuccess, id responseObject) {
} error:^(NSError *error) {
}];
}
[self clearLogFile];
} else {
// Exited Normal
[self clearLogFile];
}
}
- (void)clearLogFile {
NSString * logStr = [NSString stringWithContentsOfFile:DL_LOG_PATH encoding:NSUTF8StringEncoding error:nil];
if (logStr) {
logStr = @"";
[logStr writeToFile:DL_LOG_PATH atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
DLogOut(@"%@, %@", DL_VERSION, DL_APP);
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:ApplicationExited];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)startUp {
if ([DLFrameDebug sharedInstance].enabled) {
// Add Exception Handler
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
}
[[DLFrame_ClassLoader classLoader] loadClasses:@[
@"DLOperation"
]];
}
CopyRight@Dylan 2015-9-24.