iOS-crashログのキャプチャ保存

7945 ワード

  • 前言
  • 私のプログラムは順風満帆だと思っていたが、私たちがあなたに出会ったことを知っていた.それは嘔吐させる思い出だった.
  • バックグラウンド
  • 実际のプロジェクト开発の中で、私达は多くの异なる问题に出会うことができて、书くことがありますか?プログラミングの経験が豊富になるにつれて、手当たり次第に解决することができて、しかしもしあなたのプログラムと商店に発表して、しかもすでに审査を通じて、ある日ある取引先はフィードバックします:“あなたはこれは何のX%%X%%X%%X%%あるいはプログラムをテストスタッフにあげて、あちらの反応は閃退して、butは現場がなくて、原因を知らないで、排除してそれも1件のとても悲しい事です.
  • 結論
  • 以上述べたように、私たちはやはり情報をつかむ必要があります.第一に、あなたのプログラムをますます強くすることができます.第二に、ある程度BUGを迅速に修復することができます.第三に、あなたがどんな穴を踏んだかを知ることができます.第四に、テストの女の子とコミュニケーションすることができます.24,5679182
    幸いAppleはすでに私たちに方法を提供してくれました.そうしないと、カニを食べている人にどれだけの脳細胞を死なせなければなりませんか.
    個人的な拙見.
    これはシステム定義の1つの方法で、私たちに1つの方法のアドレス(むやみに書くことができない)を伝えて、プログラムが潰れたらこの方法をトリガーして、log情報を取得するだけではなくて、データを保存することができます.
    typedef void NSUncaughtExceptionHandler(NSException *exception);
    
    FOUNDATION_EXPORT NSUncaughtExceptionHandler * _Nullable NSGetUncaughtExceptionHandler(void);
    FOUNDATION_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);
    

    AppDelegateにそんなに冗長なコードを書かないように、少しパッケージしました
    1、先頭ファイルを先にインポートする
    #import "PQCatchErrorLog.h"
    

    2、「登録」でログを取る
                         ,
           ,          ,            ,          。
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        [PQCatchErrorLog catchLog];
        
        [PQCatchErrorLog printErrorLog];
        
        return YES;
    }
    
    

    3、...
    それから?そしてなくなりました...また提供しました
    /**
       LOG  
    
     @return log   - NSString
     */
    + (NSString *)logInfo;
    
    
    /**
       LOG  ,     
    
     @return log   - Data
     */
    + (NSData *)logData;
    
    
    /**
       error  
    
     @return         
     */
    + (BOOL)delErrorLogFile;
    

    対応する実装コード
    + (void)catchLog{
        NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
    }
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            //      
            NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
        }
        return self;
    }
    
    
    + (void)printErrorLog{
        NSLog(@"path - %@ 
    errorLog - %@",LOGFilePath,[PQCatchErrorLog logInfo]); } + (NSString *)logInfo{ return [NSString stringWithContentsOfFile:LOGFilePath encoding:NSUTF8StringEncoding error:nil]; } + (NSData *)logData{ return [[PQCatchErrorLog logInfo] dataUsingEncoding:NSUTF8StringEncoding]; } + (BOOL)delErrorLogFile{ NSError * error; [[NSFileManager defaultManager] removeItemAtPath:LOGFilePath error:&error]; if (!error) { return YES; } NSLog(@"
    - %@",error); return NO; }

    そして時間を記録するために、クラスに一緒に書くカテゴリメソッドも書きました.
    .h
    // ----------------                 -----------------
    @interface NSDate (PQCatchErrorLog)
    /**
               
     
     @return        
     */
    + (NSString *)currentDateForDateSeconds;
    @end
    
    .m
    /**
               
     
     @return        
     */
    + (NSString *)currentDateForDateSeconds{
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        NSString *destDateString1 = [dateFormatter stringFromDate:[NSDate date]];
        NSString *destDateString = [destDateString1 substringFromIndex:2];
        return destDateString;
    }
    
    

    もう一つのアドレスがつながっています
    .h
    // ----------------              -----------------
    @interface NSString (PQCatchErrorLog)
    /**
             
     
     @return   
     */
    - (NSString *)byAppendToCacheDocument;
    @end
    
    
    .m
    /**
             
     
     @return   
     */
    - (NSString *)byAppendToCacheDocument{
        NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
        return [path stringByAppendingPathComponent:self];
    }
    
    

    最後に、ロゴ情報を保存する方法について説明します.
    //      
    void UncaughtExceptionHandler(NSException *exception) {
        
        NSArray *arr = [exception callStackSymbols];//         
        
        NSString *reason = [exception reason];//    ,       
        
        NSString *name = [exception name];//    
        
        NSMutableString * log = [NSMutableString stringWithFormat:@"callStackSymbols -      :
    "]; for (NSString * str in arr) { [log appendFormat:@"%@
    ",str]; } [log appendFormat:@"
    reason - :
    %@",reason]; [log appendFormat:@"
    name - :
    %@",name]; [log insertString:[NSString stringWithFormat:@"*************** %@ *******************
    ",[NSDate currentDateForDateSeconds]] atIndex:0]; // , if (![[NSFileManager defaultManager]fileExistsAtPath:LOGFilePath]) { [[NSFileManager defaultManager]createFileAtPath:LOGFilePath contents:nil attributes:nil]; [log insertString:[NSString stringWithFormat:@"
    *************** *******************
    "] atIndex:0]; [log writeToFile:LOGFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; return; } // fileHandler NSFileHandle * fileHandler = [NSFileHandle fileHandleForWritingAtPath:LOGFilePath]; // [fileHandler seekToEndOfFile]; // [fileHandler writeData:[log dataUsingEncoding:NSUTF8StringEncoding]]; // file Handler [fileHandler closeFile]; }

    最后にわざとViewControllerの中で1つの配列の境界を越えるBUGを书いてみんなは自分で感じます:
    ***************      *******************
    *************** 16-11-28 15:32:47 *******************
    callStackSymbols -      :
    0   CoreFoundation                      0x000000010c91634b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010c37721e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010c96ebdf -[__NSSingleObjectArrayI objectAtIndex:] + 111
    3   CatchErrorLog           0x000000010bda22a3 -[ViewController viewDidLoad] + 163
    4   UIKit                               0x000000010cedac99 -[UIViewController loadViewIfRequired] + 1258
    5   UIKit                               0x000000010cedb0cc -[UIViewController view] + 27
    6   UIKit                               0x000000010cda4c51 -[UIWindow addRootViewControllerViewIfPossible] + 71
    7   UIKit                               0x000000010cda53a2 -[UIWindow _setHidden:forced:] + 293
    8   UIKit                               0x000000010cdb8cb5 -[UIWindow makeKeyAndVisible] + 42
    9   UIKit                               0x000000010cd31c89 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
    10  UIKit                               0x000000010cd37de9 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
    11  UIKit                               0x000000010cd34f69 -[UIApplication workspaceDidEndTransaction:] + 188
    12  FrontBoardServices                  0x000000010fe87723 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    13  FrontBoardServices                  0x000000010fe8759c -[FBSSerialQueue _performNext] + 189
    14  FrontBoardServices                  0x000000010fe87925 -[FBSSerialQueue _performNextFromRunLoopSource] + 45
    15  CoreFoundation                      0x000000010c8bb311 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    16  CoreFoundation                      0x000000010c8a059c __CFRunLoopDoSources0 + 556
    17  CoreFoundation                      0x000000010c89fa86 __CFRunLoopRun + 918
    18  CoreFoundation                      0x000000010c89f494 CFRunLoopRunSpecific + 420
    19  UIKit                               0x000000010cd337e6 -[UIApplication _run] + 434
    20  UIKit                               0x000000010cd39964 UIApplicationMain + 159
    21  CatchErrorLog           0x000000010bda280f main + 111
    22  libdyld.dylib                       0x000000010f6f668d start + 1
    
    reason -     :
     *** -[__NSSingleObjectArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 0]
    name -     :
     NSRangeException
    

    3行目:どの方法で
    2行目:表示されたのは配列で値を取ります
    クラッシュ原因で落札されました:配列境界
    最後の行は、例外タイプです.
    最後の最後のDEMOアドレスが役に立つ場合はstarをお願いします