天天看點

關于 iOS 程式調試 及騰訊 Bugly 的演練

程式調試

● 調用堆棧

我們先寫一個 Demo 示範一下錯誤

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self testDemo];
}

- (void)testDemo {
    NSString *str = nil;
    NSArray *array = @[@"hello word!", str];
    
    NSLog(@"%@", array);
}
           

運作後 程式很聽話的報錯了!

**2016-11-09 23:02:58.839 01-Bugly[976:81766] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[1]'**
***** First throw call stack:**
**(**
** 0   CoreFoundation                      0x000000011150034b __exceptionPreprocess + 171**
** 1   libobjc.A.dylib                     0x0000000110f6121e objc_exception_throw + 48**
** 2   CoreFoundation                      0x00000001114103b3 -[__NSPlaceholderArray initWithObjects:count:] + 275**
** 3   CoreFoundation                      0x00000001114175c4 +[NSArray arrayWithObjects:count:] + 52**
** 4   01-Bugly                            0x000000010fd06332 -[ViewController testDemo] + 98**
** 5   01-Bugly                            0x000000010fd062c9 -[ViewController viewDidLoad] + 73**
** 6   UIKit                               0x0000000111ac506d -[UIViewController loadViewIfRequired] + 1258**
** 7   UIKit                               0x0000000111ac54a0 -[UIViewController view] + 27**
** 8   UIKit                               0x000000011198f045 -[UIWindow addRootViewControllerViewIfPossible] + 71**
** 9   UIKit                               0x000000011198f796 -[UIWindow _setHidden:forced:] + 293**
** 10  UIKit                               0x00000001119a30a9 -[UIWindow makeKeyAndVisible] + 42**
** 11  UIKit                               0x000000011191c259 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818**
** 12  UIKit                               0x00000001119223b9 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731**
** 13  UIKit                               0x000000011191f539 -[UIApplication workspaceDidEndTransaction:] + 188**
** 14  FrontBoardServices                  0x000000011482576b __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24**
** 15  FrontBoardServices                  0x00000001148255e4 -[FBSSerialQueue _performNext] + 189**
** 16  FrontBoardServices                  0x000000011482596d -[FBSSerialQueue _performNextFromRunLoopSource] + 45**
** 17  CoreFoundation                      0x00000001114a5311 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17**
** 18  CoreFoundation                      0x000000011148a59c __CFRunLoopDoSources0 + 556**
** 19  CoreFoundation                      0x0000000111489a86 __CFRunLoopRun + 918**
** 20  CoreFoundation                      0x0000000111489494 CFRunLoopRunSpecific + 420**
** 21  UIKit                               0x000000011191ddb6 -[UIApplication _run] + 434**
** 22  UIKit                               0x0000000111923f34 UIApplicationMain + 159**
** 23  01-Bugly                            0x000000010fd066cf main + 111**
** 24  libdyld.dylib                       0x00000001132f868d start + 1**
** 25  ???                                 0x0000000000000001 0x0 + 1**
**)**
**libc++abi.dylib: terminating with uncaught exception of type NSException**
**(lldb)**
           

我們來看一下錯誤資訊

通常程式崩潰後 我們的目光會聚焦在錯誤資訊的最上方部分 如下:

__NSPlaceholderArray **數組** attempt to **試圖** insert nil object **插入一個空對象** from objects[1] **在索引[1]的位置**

通常看到這裡我們就開始想,程式到底哪錯了,到底在哪裡插入空對象了

然後就開始滿世界的去找,試想我們一個項目中有成百上千個檔案,我們這樣找要找到什麼時候

那我們如何找到更詳細的資訊呢?

在我們聚焦的錯誤資訊的下方就是程式錯誤的詳細資訊

它有一個專用名詞 調用堆棧

調用堆棧先執行的步驟在下方 後執行的步驟在上方

那調用堆棧給我們哪些詳細的資訊呢

10  UIKit                               0x00000001119a30a9 -[UIWindow makeKeyAndVisible] + ** 程式啟動時調用的方法 **

5   01-Bugly                            0x000000010fd062c9 -[ViewController viewDidLoad] + 73 ** 我們剛剛在ViewController viewDidLoad 中調用了testDemo 方法 **

4   01-Bugly                            0x000000010fd06332 -[ViewController testDemo] + 98 ** 我們所調用的testDemo方法 在 ViewController 中**

3   CoreFoundation                      0x00000001114175c4 +[NSArray arrayWithObjects:count:] + 52 ** 嘗試給一個數組插入資料 **

再往後程式就崩潰了 我們通過上面的資訊就可以定位到 testDemo 這個函數出問題了

錯誤原因既是 我們向數組[1]中添加一個空對象

[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[1]

發現這個線索之後 我們可以就直接去 ViewController 中 找到 testDemo 發現

NSString *str = nil;

為空

是以我們一定要學會調用堆棧的技巧 隻有善于使用這個技巧 我們才能更快的調試錯誤資訊

● 收集錯誤資訊

那我們在真機測試時同樣的錯誤提示的錯誤資訊是什麼呢?

關于 iOS 程式調試 及騰訊 Bugly 的演練

如圖所示 在真機測試時隻顯示錯誤資訊,不顯示詳細的調用堆棧的内容

那程式上線後,我們如何收集錯誤資訊呢?

這時候我們就需要使用到第三方的架構 * Bugly *

**官方網站: https://bugly.qq.com/v2/

登入 QQ 後 如下圖

關于 iOS 程式調試 及騰訊 Bugly 的演練

進入後我們注冊一下

關于 iOS 程式調試 及騰訊 Bugly 的演練

注冊完成後 我們來內建 第三方架構 選中 SDK -> iOS SDK 使用指南

關于 iOS 程式調試 及騰訊 Bugly 的演練

在這裡我推薦使用 CocoaPods 內建 Bugly 架構

打開Mac自帶終端

cd "項目根目錄" pod init

建立 Podfile

将項目中 Podfile 拖入 Xcode 中

不要删除檔案中的内容

在 target 下方 粘貼 如下内容

pod 'Bugly'

回到終端中

pod install --no-repo-update

Tip: 我們可以通過

--help

找到 CocoaPods 的幫助資訊 這樣,需要的東西我們就可以直接複制粘貼~~

接下來我們回到項目中 這時候記得點 白色 的檔案

來到項目的 AppDelegate.m 中初始化 Bugly

//先導入頭檔案
#import <Bugly/Bugly.h>
           
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
//下面的内容一定要放在第一句 在程式啟動時 下面的代碼全部能監聽到!!!!
        [Bugly startWithAppId:@"此處替換為你的AppId"]; 
        return YES; 
  }
           

此處的 AppID 在我們剛剛注冊的 App 中 如下圖:

關于 iOS 程式調試 及騰訊 Bugly 的演練

替換 AppID 後 我們導入架構的工作就完成了!

此時我們回到項目中運作程式 真機測試 繼續讓程式崩潰下~

崩潰後 稍等片刻回到 網站中檢視崩潰日志

這裡注意: 程式崩潰後 會在 AppDelegate.h 中打一個 斷點**

此時後面的程式就不會繼續執行 不執行就會導緻錯誤資訊無法送出到 Bugly 中

進而導緻我們在崩潰日志中 無法顯示崩潰結果

此時 我們回到手機中 點選執行個體程式 閃退即可**

關于 iOS 程式調試 及騰訊 Bugly 的演練

點選進入 錯誤資訊

關于 iOS 程式調試 及騰訊 Bugly 的演練

與我們在模拟器中 調用堆棧 的内容一緻 ,并且它還幫我們将錯誤資訊 标藍

末語:

當我們導入騰訊的第三方架構 Bugly 後

即便我們的程式上線了 我們也可以知道程式崩潰在哪裡!

即簡單 又友善

繼續閱讀