iOS 集成 Bugly 二三事

Bugly 官網(wǎng)

騰訊Bugly腺毫,為移動(dòng)開發(fā)者提供專業(yè)的異常上報(bào)和運(yùn)營(yíng)統(tǒng)計(jì),幫助開發(fā)者快速發(fā)現(xiàn)并解決異常个唧,同時(shí)掌握產(chǎn)品運(yùn)營(yíng)動(dòng)態(tài)渠退,及時(shí)跟進(jìn)用戶反饋忙迁。

最近 iOS 項(xiàng)目中集成了 Bugly 脐彩,集成該框架的過(guò)程中,90%的問題通過(guò)仔細(xì)閱讀 Bugly 官方文檔 都可以解決姊扔。

?? 本文并不會(huì)教你如何注冊(cè)申請(qǐng) Bugly 帳號(hào)惠奸,也不會(huì)教你如何集成 Bugly SDK,因?yàn)楣俜轿臋n是最權(quán)威的恰梢,這里只是記錄幾個(gè)注意點(diǎn)(傳說(shuō)中的坑3看ā)。

初始化 Bugly 的注意點(diǎn)

方式一删豺,最簡(jiǎn)單

在工程AppDelegate.mapplication:didFinishLaunchingWithOptions:方法中初始化:

#import "AppDelegate.h"
#import <Bugly/Bugly.h>

// Bugly 帳號(hào)中創(chuàng)建產(chǎn)品后,產(chǎn)品信息中的 AppId
static NSString *const KBuglyAppId = @"**********"; 

@implementation AppDelegate
  
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [Bugly startWithAppId:KBuglyAppId];
    return YES;
}

方式二愧怜,官方文檔中的"高級(jí)功能"

Bugly支持讀取 Info.plist 文件讀取SDK初始化參數(shù)呀页,可配置的參數(shù)如下:

- Appid
    - Key: BuglyAppIDString
    - Value: 字符串類型
- 渠道標(biāo)識(shí)
    - Key: BuglyAppChannelString
    - Value: 字符串類型
- 版本信息
    - Key: BuglyAppVersionString
    - Value: 字符串類型
- 開啟Debug信息顯示
    - Key: BuglyDebugEnable
    - Value: BOOL類型

我們?cè)O(shè)置 Info.plist 文件如下:

image

如下初始化方式,則會(huì)讀取Info.plist內(nèi)添加的key-value配置進(jìn)行SDK初始化:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 讀取Info.plist中的參數(shù)初始化SDK
    [Bugly startWithAppId:nil];
    return YES;
}

以上方式初始化 Bugly 確實(shí)沒問題拥坛,可是默認(rèn)的 BuglyConfig 還有幾個(gè)監(jiān)控開關(guān)沒開蓬蝶,我也想順便開啟一下:

// 可能存在問題的代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
    BuglyConfig *config = [[BuglyConfig alloc] init];
    config.blockMonitorEnable = YES; // 卡頓監(jiān)控開關(guān),默認(rèn)關(guān)閉
    config.blockMonitorTimeout = 5;
    config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件記錄開關(guān)猜惋,默認(rèn)關(guān)閉

    // 讀取Info.plist中的參數(shù)初始化SDK
    [Bugly startWithAppId:nil config:config];
    
    return YES;
}

?? 注意丸氛,這樣初始化就會(huì)有問題,如果配置了Info.plist字段著摔,又在初始化時(shí)傳入了自定義的 BuglyConfig 實(shí)例缓窜,那么在 Info.plist 中配置的 BuglyAppChannelStringBuglyAppVersionString谍咆、BuglyDebugEnable 會(huì)因?yàn)楸桓采w而失效禾锤。

方式三,自定義配置

如果需要自定義配置 BuglyConfig 實(shí)例摹察,這里就不建議不同時(shí)配置Info.plist字段(或者可以只配置BuglyAppIDString字段):

完整代碼:

#import "AppDelegate.h"
#import <Bugly/Bugly.h>

static NSString *const KBuglyAppId = @"**********";

@implementation AppDelegate

#pragma mark - UIApplicationDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [self p_configureForBugly]; 
  
    return YES;
}

#pragma mark - Private

- (void)p_configureForBugly {
    BuglyConfig *config = [[BuglyConfig alloc] init];
    config.channel = @"App Store";
    config.blockMonitorEnable = YES; // 卡頓監(jiān)控開關(guān)恩掷,默認(rèn)關(guān)閉
    config.blockMonitorTimeout = 5;
    config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件記錄開關(guān),默認(rèn)關(guān)閉
    config.delegate = self;

#ifdef DEBUG
    config.debugMode = YES; // debug 模式下供嚎,開啟調(diào)試模式
    config.reportLogLevel = BuglyLogLevelVerbose; // 設(shè)置打印日志級(jí)別
#else
    config.debugMode = NO; // release 模式下黄娘,關(guān)閉調(diào)試模式
    config.reportLogLevel = BuglyLogLevelWarn; // 設(shè)置自定義日志上報(bào)的級(jí)別,默認(rèn)不上報(bào)自定義日志
#endif
    
    [Bugly startWithAppId:KBuglyAppId config:config];
}

?? 如果你配置完 Bugly 之后克滴,

BLYLogError(fmt, ...)
BLYLogWarn(fmt, ...)
BLYLogInfo(fmt, ...)
BLYLogDebug(fmt, ...)
BLYLogVerbose(fmt, ...)

如上的日志不會(huì)在控制臺(tái)輸出逼争,或者部分類型日志不會(huì)輸出,那你應(yīng)該注意到需要設(shè)置這段代碼:

#ifdef DEBUG
    config.debugMode = YES; // debug 模式下劝赔,開啟調(diào)試模式
    config.reportLogLevel = BuglyLogLevelVerbose; // 設(shè)置打印日志級(jí)別
#else
    config.debugMode = NO; // release 模式下氮凝,關(guān)閉調(diào)試模式
    config.reportLogLevel = BuglyLogLevelWarn; // 設(shè)置自定義日志上報(bào)的級(jí)別,默認(rèn)不上報(bào)自定義日志
#endif

關(guān)于 SDK 回調(diào)問題

BuglyConfig.h文件中還有一個(gè)可以遵守的協(xié)議 BuglyDelegate 用于在系統(tǒng)崩潰時(shí)可以同時(shí)上傳自定義數(shù)據(jù)望忆。

@protocol BuglyDelegate <NSObject>

@optional
/**
 *  發(fā)生異常時(shí)回調(diào)
 *
 *  @param exception 異常信息
 *
 *  @return 返回需上報(bào)記錄罩阵,隨異常上報(bào)一起上報(bào)
 */
- (NSString * BLY_NULLABLE)attachmentForException:(NSException * BLY_NULLABLE)exception;

@end

我遇到的問題是竿秆,出于代碼清晰的目的,將應(yīng)用初始化配置稿壁、第三方框架初始化配置幽钢、推送、分享相關(guān)的代碼都放在分類中了:

image

并且在分類中遵守了 <BuglyDelegate> 協(xié)議傅是,也實(shí)現(xiàn)了簡(jiǎn)單的回調(diào)方法:

- (NSString * BLY_NULLABLE)attachmentForException:(NSException * BLY_NULLABLE)exception {
    return @"需要上傳的數(shù)據(jù)...";
}

正常情況下匪燕,應(yīng)用發(fā)生崩潰后,Bugly 會(huì)立即上報(bào)異常喧笔,同時(shí)在「崩潰分析」-「跟蹤數(shù)據(jù)」-「附件信息」中顯示回調(diào)方法中上傳的數(shù)據(jù)文件 crash_attach.log

image

實(shí)際上把回調(diào)代碼寫在分類中時(shí)帽驯,應(yīng)用發(fā)生崩潰時(shí),并不會(huì)觸發(fā)協(xié)議方法书闸。所以務(wù)必要把所有與 Bugly 初始化及回調(diào)代碼寫在 AppDelegate.m 文件中尼变。

最后,附上 Bugly 集成的完整正確代碼示例:

#import "AppDelegate.h"
#import <Bugly/Bugly.h>

static NSString *const KBuglyAppId = @"**********";

@interface AppDelegate () <BuglyDelegate>

@end

@implementation AppDelegate

#pragma mark - UIApplicationDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    [self p_configureForBugly];
  
    return YES;
}

#pragma mark - Private

- (void)p_configureForBugly {
    BuglyConfig *config = [[BuglyConfig alloc] init];
    config.channel = @"App Store";
    config.blockMonitorEnable = YES; // 卡頓監(jiān)控開關(guān)浆劲,默認(rèn)關(guān)閉
    config.blockMonitorTimeout = 5;
    config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件記錄開關(guān)嫌术,默認(rèn)關(guān)閉
    config.delegate = self;

#ifdef DEBUG
    config.debugMode = YES; // debug 模式下,開啟調(diào)試模式
    config.reportLogLevel = BuglyLogLevelVerbose; // 設(shè)置自定義日志上報(bào)的級(jí)別牌借,默認(rèn)不上報(bào)自定義日志
#else
    config.debugMode = NO; // release 模式下度气,關(guān)閉調(diào)試模式
    config.reportLogLevel = BuglyLogLevelWarn;
#endif
    
    [Bugly startWithAppId:KBuglyAppId config:config];
}

#pragma mark - BuglyDelegate

- (NSString * BLY_NULLABLE)attachmentForException:(NSException * BLY_NULLABLE)exception {
    NSDictionary *dictionary = @{@"Name":exception.name,
                                 @"Reason":exception.reason};
    return [NSString stringWithFormat:@"Exception:%@",dictionary];
}

@end

過(guò)早的優(yōu)化是萬(wàn)惡之源∨虮ǎ——高德納

對(duì)依賴進(jìn)行抽象化和封裝

參考對(duì) Flurry 的封裝方法

#import <Foundation/Foundation.h>

/**
 封裝 Flurry 埋點(diǎn)
 */
@interface HPInstrumentation : NSObject

+(void)startWithAPIKey:(NSString *)apiKey;
+(void)logEvent:(NSString *)name;
+(void)logEvent:(NSString *)name withParams:(NSDictionary *)params;

+(void)logPageViewForTabBarController:(UITabBarController *)vc;

@end

#import "HPInstrumentation.h"
#import "Flurry.h"

@implementation HPInstrumentation

+(void)startWithAPIKey:(NSString *)apiKey
{
    [Flurry startSession:apiKey];
}

+(void)logEvent:(NSString *)name
{
    NSLog(@"<HPInst> %@", name);
    [Flurry logEvent:name];
}

+(void)logEvent:(NSString *)name withParams:(NSDictionary *)params
{
    NSLog(@"<HPInst> %@ -> %@", name, params);
    [Flurry logEvent:name withParameters:params];
}

+(void)logPageViewForTabBarController:(UITabBarController *)vc {
    NSLog(@"<HPInst> PV: %@", [vc class]);
    [Flurry logAllPageViewsForTarget:vc];
}

@end

嘗試對(duì) Bugly 進(jìn)行封裝

#import <Foundation/Foundation.h>

/**
 對(duì)依賴進(jìn)行抽象化和封裝
 如果直接在項(xiàng)目中使用崩潰報(bào)告系統(tǒng)磷籍,那么埋點(diǎn)會(huì)分散在項(xiàng)目中的各個(gè)角落,不利于后期替換或更改现柠。
 低耦合:增加一個(gè)中間層之后择示,可以隨時(shí)對(duì)依賴的第三方框架進(jìn)行切換,無(wú)須再去修改分散在各個(gè)類中的代碼晒旅。
 */
@interface HQLInstrumentation : NSObject

+ (void)logEvent:(NSString *)name;
+ (void)logEvent:(NSString *)name withParamenters:(NSString *)parameters;

@end

#import "HQLInstrumentation.h"
#import <Bugly/Bugly.h>

@implementation HQLInstrumentation

+ (void)logEvent:(NSString *)name {
    [BuglyLog log:@"%@", name];
}

+ (void)logEvent:(NSString *)name withParamenters:(NSString *)parameters {
    [BuglyLog log:@"%@:%@",name,parameters];
}

@end

相關(guān)框架

  • JJException - 保護(hù) Objective-C 應(yīng)用不閃退的框架栅盲。
  • KSCrash - iOS崩潰報(bào)告框架
  • PLCrashReporter - Reliable, open-source crash reporting for iOS and Mac OS X.

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市废恋,隨后出現(xiàn)的幾起案子谈秫,更是在濱河造成了極大的恐慌,老刑警劉巖鱼鼓,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拟烫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡迄本,警方通過(guò)查閱死者的電腦和手機(jī)硕淑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人置媳,你說(shuō)我怎么就攤上這事于樟。” “怎么了拇囊?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵迂曲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我寥袭,道長(zhǎng)路捧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任传黄,我火速辦了婚禮杰扫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘膘掰。我一直安慰自己章姓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布炭序。 她就那樣靜靜地躺著,像睡著了一般苍日。 火紅的嫁衣襯著肌膚如雪惭聂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天相恃,我揣著相機(jī)與錄音辜纲,去河邊找鬼。 笑死拦耐,一個(gè)胖子當(dāng)著我的面吹牛耕腾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杀糯,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼扫俺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了固翰?” 一聲冷哼從身側(cè)響起狼纬,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骂际,沒想到半個(gè)月后疗琉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡歉铝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年盈简,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柠贤,死狀恐怖香浩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情种吸,我是刑警寧澤弃衍,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站坚俗,受9級(jí)特大地震影響镜盯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜猖败,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一速缆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恩闻,春花似錦艺糜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至尉剩,卻和暖如春真慢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背理茎。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工黑界, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人皂林。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓朗鸠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親础倍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烛占,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,754評(píng)論 25 707
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實(shí)...
    香橙柚子閱讀 23,794評(píng)論 8 183
  • 經(jīng)典面試題 Edit on 9月20日沟启。上周五的Bloomberg on campus interview 考了這...
    98Future閱讀 291評(píng)論 0 1
  • 菊次郎的夏天扰楼,一部無(wú)聊又有趣的公路電影。 看了三次美浦,終于把它看完了弦赖,看到中間,無(wú)數(shù)次想睡著浦辨,又不想錯(cuò)過(guò)精彩的情節(jié)蹬竖。...
    皮球君閱讀 525評(píng)論 4 2
  • 相信大多數(shù)人都會(huì)熬夜币厕,已經(jīng)成了家常便飯列另,但熬夜的理由,參差不齊旦装。 有些人為了工作加班加點(diǎn)所迫页衙,坐在電腦面前發(fā)呆,頭...
    Ruby_于楊閱讀 324評(píng)論 0 2