diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index de285085..99e52251 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -532,6 +532,7 @@ 4C7F2A6B2E0BE7E7002F5058 /* FirstRechargeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7F2A6A2E0BE7E7002F5058 /* FirstRechargeManager.m */; }; 4C815A172CFEB758002A46A6 /* SuperBlockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */; }; 4C84A9C22E5ED593002C10FC /* GameBannerGestureManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C84A9C12E5ED593002C10FC /* GameBannerGestureManager.m */; }; + 4C84A9CB2E602B1A002C10FC /* BuglyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C84A9CA2E602B1A002C10FC /* BuglyManager.m */; }; 4C85DB812DCDD83E00FD9839 /* CreateEventPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DB802DCDD83E00FD9839 /* CreateEventPresenter.m */; }; 4C85DB842DCDDD6800FD9839 /* CreateEventViewControllerV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DB832DCDDD6800FD9839 /* CreateEventViewControllerV2.m */; }; 4C864A022D55F4F600191AE0 /* LuckyPackagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C864A012D55F4F600191AE0 /* LuckyPackagePresenter.m */; }; @@ -2728,6 +2729,8 @@ 4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SuperBlockViewController.m; sourceTree = ""; }; 4C84A9C02E5ED593002C10FC /* GameBannerGestureManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameBannerGestureManager.h; sourceTree = ""; }; 4C84A9C12E5ED593002C10FC /* GameBannerGestureManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameBannerGestureManager.m; sourceTree = ""; }; + 4C84A9C92E602B1A002C10FC /* BuglyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BuglyManager.h; sourceTree = ""; }; + 4C84A9CA2E602B1A002C10FC /* BuglyManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BuglyManager.m; sourceTree = ""; }; 4C85DB7F2DCDD83E00FD9839 /* CreateEventPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreateEventPresenter.h; sourceTree = ""; }; 4C85DB802DCDD83E00FD9839 /* CreateEventPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CreateEventPresenter.m; sourceTree = ""; }; 4C85DB822DCDDD6800FD9839 /* CreateEventViewControllerV2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreateEventViewControllerV2.h; sourceTree = ""; }; @@ -8282,6 +8285,8 @@ E81C279926EB64BA0031E639 /* Global */ = { isa = PBXGroup; children = ( + 4C84A9C92E602B1A002C10FC /* BuglyManager.h */, + 4C84A9CA2E602B1A002C10FC /* BuglyManager.m */, E81C279A26EB65560031E639 /* YUMIMacroUitls.h */, E81C279B26EEEC620031E639 /* YUMIConstant.h */, E81C279C26EEEC620031E639 /* YUMIConstant.m */, @@ -12137,6 +12142,7 @@ E87C54BE2823CC5B0051AA11 /* XPMineResetLoginPwdPresenter.m in Sources */, 237852A42C082A9800E360AC /* MSRoomGameSendTextView.m in Sources */, E85E7B322A4EB0D300B6D00A /* XPGuildAnchorIncomeSectionView.m in Sources */, + 4C84A9CB2E602B1A002C10FC /* BuglyManager.m in Sources */, E87C0AA027D9DE6400CB2241 /* RoomFaceSendInfoModel.m in Sources */, 1464C5F629A4CA8C00AF7C94 /* XPIAPRechargeCollectionViewCell.m in Sources */, E8751E6328A646400056EF44 /* XPSailingRankView.m in Sources */, diff --git a/YuMi/Appdelegate/AppDelegate+ThirdConfig.m b/YuMi/Appdelegate/AppDelegate+ThirdConfig.m index fb6d65d6..12fb5ee5 100644 --- a/YuMi/Appdelegate/AppDelegate+ThirdConfig.m +++ b/YuMi/Appdelegate/AppDelegate+ThirdConfig.m @@ -27,6 +27,7 @@ #import #import +#import "BuglyManager.h" #import #import "YuMi-swift.h" @@ -78,23 +79,11 @@ UIKIT_EXTERN NSString * adImageName; */ - (void) configBugly { - - BuglyConfig *config = [[BuglyConfig alloc] init]; - config.blockMonitorTimeout = 5; - + // 使用 BuglyManager 统一管理 Bugly 配置 #ifdef DEBUG - config.debugMode = NO;//YES; // debug 模式下,开启调试模式 - config.channel = [YYUtility getAppSource]; - config.reportLogLevel = BuglyLogLevelWarn;// BuglyLogLevelSilent; // BuglyLogLevelVerbose; // 设置打印日志级别 - [Bugly startWithAppId:@"c937fd00f7" config:config]; + [[BuglyManager sharedManager] configureWithAppId:@"c937fd00f7" debug:YES]; #else - config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件记录开关,默认关闭 - config.debugMode = NO; // release 模式下,关闭调试模式 - config.channel = [YYUtility getAppSource];; - config.blockMonitorEnable = YES; // 卡顿监控开关,默认关闭 - config.reportLogLevel = BuglyLogLevelWarn; // 设置自定义日志上报的级别,默认不上报自定义日志 - NSString *buylyKey = @"8627948559"; - [Bugly startWithAppId:buylyKey config:config]; + [[BuglyManager sharedManager] configureWithAppId:@"8627948559" debug:NO]; #endif } - (void)configNIMSDK { diff --git a/YuMi/Global/BuglyManager.h b/YuMi/Global/BuglyManager.h new file mode 100644 index 00000000..968207f7 --- /dev/null +++ b/YuMi/Global/BuglyManager.h @@ -0,0 +1,115 @@ +// +// BuglyManager.h +// YuMi +// +// Created by BuglyManager +// Copyright © 2024 YuMi. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class BuglyManager; + +/** + * BuglyManager 代理协议 + * 用于监听卡顿和性能问题 + */ +@protocol BuglyManagerDelegate + +@optional +/** + * 检测到卡顿时的回调 + * @param manager BuglyManager 实例 + * @param duration 卡顿持续时间(秒) + */ +- (void)buglyManager:(BuglyManager *)manager didDetectLag:(NSTimeInterval)duration; + +/** + * 检测到主线程阻塞时的回调 + * @param manager BuglyManager 实例 + * @param duration 阻塞持续时间(秒) + */ +- (void)buglyManager:(BuglyManager *)manager didDetectBlock:(NSTimeInterval)duration; + +@end + +/** + * Bugly 统一管理类 + * 封装所有 Bugly 相关操作,提供统一的错误上报和性能监控接口 + */ +@interface BuglyManager : NSObject + +/** + * 单例访问方法 + * @return BuglyManager 单例实例 + */ ++ (instancetype)sharedManager; + +/** + * 设置代理对象 + */ +@property (nonatomic, assign) id delegate; + +/** + * 配置并启动 Bugly + * @param appId Bugly 应用 ID + * @param isDebug 是否为调试模式 + */ +- (void)configureWithAppId:(NSString *)appId debug:(BOOL)isDebug; + +/** + * 上报错误信息 + * @param domain 错误域 + * @param code 错误码 + * @param userInfo 错误详细信息 + */ +- (void)reportError:(NSString *)domain + code:(NSInteger)code + userInfo:(NSDictionary *)userInfo; + +/** + * 上报业务错误(简化版) + * @param message 错误消息 + * @param code 错误码 + * @param context 错误上下文信息 + */ +- (void)reportBusinessError:(NSString *)message + code:(NSInteger)code + context:(NSDictionary *)context; + +/** + * 上报网络请求异常 + * @param uid 用户ID + * @param api 接口路径 + * @param code 错误码 + * @param userInfo 额外信息 + */ +- (void)reportNetworkError:(NSString *)uid + api:(NSString *)api + code:(NSInteger)code + userInfo:(NSDictionary *)userInfo; + +/** + * 上报内购相关错误 + * @param uid 用户ID + * @param transactionId 交易ID + * @param orderId 订单ID + * @param status 状态码 + * @param context 上下文信息 + */ +- (void)reportIAPError:(NSString *)uid + transactionId:(NSString *)transactionId + orderId:(NSString *)orderId + status:(NSInteger)status + context:(NSDictionary *)context; + +/** + * 手动触发卡顿检测 + */ +- (void)startLagDetection; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/BuglyManager.m b/YuMi/Global/BuglyManager.m new file mode 100644 index 00000000..d824d45d --- /dev/null +++ b/YuMi/Global/BuglyManager.m @@ -0,0 +1,262 @@ +// +// BuglyManager.m +// YuMi +// +// Created by BuglyManager +// Copyright © 2024 YuMi. All rights reserved. +// + +#import "BuglyManager.h" +#import + +@interface BuglyManager () + +@property (nonatomic, strong) NSString *appId; +@property (nonatomic, assign) BOOL isConfigured; + +@end + +@implementation BuglyManager + +#pragma mark - Singleton + ++ (instancetype)sharedManager { + static BuglyManager *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[BuglyManager alloc] init]; + }); + return instance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _isConfigured = NO; + } + return self; +} + +#pragma mark - BuglyDelegate +- (NSString * BLY_NULLABLE)attachmentForException:(NSException * BLY_NULLABLE)exception { + NSString *message = [NSString stringWithFormat:@"%@ - %@", exception.name, exception.reason]; + [self handleLagDetection:message]; + return message; +} + +#pragma mark - Public Methods + +- (void)configureWithAppId:(NSString *)appId debug:(BOOL)isDebug { + if (self.isConfigured) { + NSLog(@"[BuglyManager] Bugly 已经配置,跳过重复配置"); + return; + } + + if (!appId || appId.length == 0) { + NSLog(@"[BuglyManager] 错误:appId 不能为空"); + return; + } + + self.appId = appId; + + // 创建 Bugly 配置 + BuglyConfig *config = [[BuglyConfig alloc] init]; + config.delegate = self; + + // 基础配置 + config.blockMonitorTimeout = 3.0; // 卡顿监控超时时间:3秒 + config.blockMonitorEnable = YES; // 启用卡顿监控 + + // 调试模式配置 + if (isDebug) { + config.debugMode = NO; // 生产环境关闭调试模式 + config.channel = [self getAppChannel]; + config.reportLogLevel = BuglyLogLevelWarn; // 设置日志级别 + } else { + config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件记录 + config.debugMode = NO; + config.channel = [self getAppChannel]; + config.blockMonitorEnable = YES; + config.reportLogLevel = BuglyLogLevelWarn; + } + // 启动 Bugly + [Bugly startWithAppId:appId config:config]; + + self.isConfigured = YES; + + NSLog(@"[BuglyManager] Bugly 配置完成 - AppID: %@, Debug: %@", appId, isDebug ? @"YES" : @"NO"); +} + +- (void)reportError:(NSString *)domain + code:(NSInteger)code + userInfo:(NSDictionary *)userInfo { + + if (!self.isConfigured) { + NSLog(@"[BuglyManager] 错误:Bugly 未配置,无法上报错误"); + return; + } + + if (!domain || domain.length == 0) { + domain = @"UnknownError"; + } + + // 创建错误对象 + NSError *error = [NSError errorWithDomain:domain + code:code + userInfo:userInfo]; + + // 异步上报错误 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [Bugly reportError:error]; + NSLog(@"[BuglyManager] 错误上报成功 - Domain: %@, Code: %ld", domain, (long)code); + }); +} + +- (void)reportBusinessError:(NSString *)message + code:(NSInteger)code + context:(NSDictionary *)context { + + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + + // 添加基础信息 + if (message && message.length > 0) { + [userInfo setObject:message forKey:@"error_message"]; + } + [userInfo setObject:@(code) forKey:@"error_code"]; + [userInfo setObject:@"BusinessError" forKey:@"error_type"]; + + // 添加上下文信息 + if (context && context.count > 0) { + [userInfo addEntriesFromDictionary:context]; + } + + // 添加时间戳 + [userInfo setObject:@([[NSDate date] timeIntervalSince1970]) forKey:@"timestamp"]; + + [self reportError:@"BusinessError" code:code userInfo:userInfo]; +} + +- (void)reportNetworkError:(NSString *)uid + api:(NSString *)api + code:(NSInteger)code + userInfo:(NSDictionary *)userInfo { + + NSMutableDictionary *errorInfo = [NSMutableDictionary dictionary]; + + // 添加网络错误特有信息 + if (uid && uid.length > 0) { + [errorInfo setObject:uid forKey:@"user_id"]; + } + if (api && api.length > 0) { + [errorInfo setObject:api forKey:@"api_path"]; + } + [errorInfo setObject:@(code) forKey:@"http_code"]; + [errorInfo setObject:@"NetworkError" forKey:@"error_type"]; + + // 添加调用栈信息 + [errorInfo setObject:[NSThread callStackSymbols] forKey:@"call_stack_symbols"]; + + // 合并额外信息 + if (userInfo && userInfo.count > 0) { + [errorInfo addEntriesFromDictionary:userInfo]; + } + + [self reportError:@"NetworkError" code:code userInfo:errorInfo]; +} + +- (void)reportIAPError:(NSString *)uid + transactionId:(NSString *)transactionId + orderId:(NSString *)orderId + status:(NSInteger)status + context:(NSDictionary *)context { + + NSMutableDictionary *errorInfo = [NSMutableDictionary dictionary]; + + // 添加内购错误特有信息 + if (uid && uid.length > 0) { + [errorInfo setObject:uid forKey:@"user_id"]; + } + if (transactionId && transactionId.length > 0) { + [errorInfo setObject:transactionId forKey:@"transaction_id"]; + } + if (orderId && orderId.length > 0) { + [errorInfo setObject:orderId forKey:@"order_id"]; + } + [errorInfo setObject:@(status) forKey:@"status_code"]; + [errorInfo setObject:@"IAPError" forKey:@"error_type"]; + + // 添加状态描述 + NSString *statusMsg = [self getIAPStatusMessage:status]; + if (statusMsg) { + [errorInfo setObject:statusMsg forKey:@"status_message"]; + } + + // 合并上下文信息 + if (context && context.count > 0) { + [errorInfo addEntriesFromDictionary:context]; + } + + // 生成错误码 + NSInteger errorCode = -20000 + status; + + [self reportError:@"IAPError" code:errorCode userInfo:errorInfo]; +} + +- (void)startLagDetection { + if (!self.isConfigured) { + NSLog(@"[BuglyManager] 错误:Bugly 未配置,无法启动卡顿检测"); + return; + } + + NSLog(@"[BuglyManager] 手动启动卡顿检测"); + // Bugly 会自动进行卡顿检测,这里主要是日志记录 +} + +#pragma mark - Private Methods + +- (void)handleLagDetection:(NSString *)stackTrace { + NSLog(@"[BuglyManager] 🚨 检测到卡顿 - StackTrace: %@", stackTrace); + + // 计算卡顿持续时间(这里假设为3秒,实际应该从 Bugly 配置中获取) + NSTimeInterval duration = 3.0; + + // 通知代理 + if (self.delegate && [self.delegate respondsToSelector:@selector(buglyManager:didDetectLag:)]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [(id)self.delegate buglyManager:self didDetectLag:duration]; + }); + } + + // TODO: 触发卡顿通知逻辑 + // 1. 记录卡顿信息到本地日志 + // 2. 发送本地通知 + // 3. 记录到性能监控系统 + // 4. 触发用户反馈机制 +} + +- (NSString *)getAppChannel { + // 这里应该调用项目中的工具方法获取渠道信息 + // 暂时返回默认值 + return @"AppStore"; +} + +- (NSString *)getIAPStatusMessage:(NSInteger)status { + switch (status) { + case 0: + return @"尝试验单"; + case 1: + return @"验单-补单成功"; + case 2: + return @"验单-补单失败"; + case 3: + return @"验单-补单 id 异常"; + case 4: + return @"重试次数过多"; + case 5: + return @"过期交易清理"; + default: + return @"未知状态"; + } +} + +@end diff --git a/YuMi/Global/BuglyManagerExample.h b/YuMi/Global/BuglyManagerExample.h new file mode 100644 index 00000000..dd3d9459 --- /dev/null +++ b/YuMi/Global/BuglyManagerExample.h @@ -0,0 +1,42 @@ +// +// BuglyManagerExample.h +// YuMi +// +// Created by BuglyManager Example +// Copyright © 2024 YuMi. All rights reserved. +// + +#import +#import "BuglyManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * BuglyManager 使用示例类 + * 展示如何使用 BuglyManager 的各种功能 + */ +@interface BuglyManagerExample : NSObject + +/** + * 设置 Bugly 代理 + */ +- (void)setupBuglyDelegate; + +/** + * 上报业务错误示例 + */ +- (void)reportBusinessErrorExample; + +/** + * 上报网络错误示例 + */ +- (void)reportNetworkErrorExample; + +/** + * 上报内购错误示例 + */ +- (void)reportIAPErrorExample; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Global/BuglyManagerExample.m b/YuMi/Global/BuglyManagerExample.m new file mode 100644 index 00000000..5810ec34 --- /dev/null +++ b/YuMi/Global/BuglyManagerExample.m @@ -0,0 +1,79 @@ +// +// BuglyManagerExample.m +// YuMi +// +// Created by BuglyManager Example +// Copyright © 2024 YuMi. All rights reserved. +// + +#import "BuglyManagerExample.h" +#import "BuglyManager.h" + +@implementation BuglyManagerExample + +#pragma mark - 使用示例 + +// 示例1:设置代理监听卡顿 +- (void)setupBuglyDelegate { + [BuglyManager sharedManager].delegate = self; +} + +// 示例2:上报业务错误 +- (void)reportBusinessErrorExample { + NSDictionary *context = @{ + @"page": @"HomePage", + @"action": @"loadData", + @"timestamp": @([[NSDate date] timeIntervalSince1970]) + }; + + [[BuglyManager sharedManager] reportBusinessError:@"数据加载失败" + code:1001 + context:context]; +} + +// 示例3:上报网络错误 +- (void)reportNetworkErrorExample { + NSDictionary *userInfo = @{ + @"requestParams": @{@"userId": @"12345"}, + @"responseData": @"服务器错误" + }; + + [[BuglyManager sharedManager] reportNetworkError:@"user123" + api:@"user/profile" + code:500 + userInfo:userInfo]; +} + +// 示例4:上报内购错误 +- (void)reportIAPErrorExample { + NSDictionary *context = @{ + @"retryCount": @3, + @"productId": @"com.yumi.coin100" + }; + + [[BuglyManager sharedManager] reportIAPError:@"user123" + transactionId:@"txn_123456" + orderId:@"order_789" + status:2 + context:context]; +} + +#pragma mark - BuglyManagerDelegate + +- (void)buglyManager:(BuglyManager *)manager didDetectLag:(NSTimeInterval)duration { + NSLog(@"[Example] 检测到卡顿,持续时间: %.2f 秒", duration); + + // TODO: 在这里实现卡顿通知逻辑 + // 1. 记录到本地日志 + // 2. 发送本地通知 + // 3. 上报到性能监控系统 + // 4. 触发用户反馈机制 +} + +- (void)buglyManager:(BuglyManager *)manager didDetectBlock:(NSTimeInterval)duration { + NSLog(@"[Example] 检测到主线程阻塞,持续时间: %.2f 秒", duration); + + // TODO: 在这里实现阻塞通知逻辑 +} + +@end diff --git a/YuMi/Global/BuglyManager_README.md b/YuMi/Global/BuglyManager_README.md new file mode 100644 index 00000000..145ac385 --- /dev/null +++ b/YuMi/Global/BuglyManager_README.md @@ -0,0 +1,129 @@ +# BuglyManager 使用说明 + +## 概述 + +`BuglyManager` 是一个统一的 Bugly 管理类,封装了所有 Bugly 相关操作,提供统一的错误上报和性能监控接口。 + +## 主要功能 + +### 1. 统一错误上报 +- 业务错误上报 +- 网络错误上报 +- 内购错误上报 +- 自定义错误上报 + +### 2. 卡顿监听 +- 自动检测主线程卡顿 +- 支持代理回调通知 +- 可配置卡顿阈值 + +### 3. 性能监控 +- 主线程阻塞检测 +- 异常退出检测 +- 自定义日志级别 + +## 使用方法 + +### 1. 初始化配置 + +```objc +// 在 AppDelegate 中配置 +#ifdef DEBUG + [[BuglyManager sharedManager] configureWithAppId:@"c937fd00f7" debug:YES]; +#else + [[BuglyManager sharedManager] configureWithAppId:@"8627948559" debug:NO]; +#endif +``` + +### 2. 设置代理监听卡顿 + +```objc +// 在需要监听卡顿的类中 +@interface YourClass : NSObject +@end + +@implementation YourClass +- (void)setupBuglyDelegate { + [BuglyManager sharedManager].delegate = self; +} + +- (void)buglyManager:(BuglyManager *)manager didDetectLag:(NSTimeInterval)duration { + NSLog(@"检测到卡顿,持续时间: %.2f 秒", duration); + // TODO: 实现卡顿通知逻辑 +} +@end +``` + +### 3. 错误上报 + +#### 业务错误上报 +```objc +NSDictionary *context = @{ + @"page": @"HomePage", + @"action": @"loadData" +}; + +[[BuglyManager sharedManager] reportBusinessError:@"数据加载失败" + code:1001 + context:context]; +``` + +#### 网络错误上报 +```objc +NSDictionary *userInfo = @{ + @"requestParams": @{@"userId": @"12345"}, + @"responseData": @"服务器错误" +}; + +[[BuglyManager sharedManager] reportNetworkError:@"user123" + api:@"user/profile" + code:500 + userInfo:userInfo]; +``` + +#### 内购错误上报 +```objc +NSDictionary *context = @{ + @"retryCount": @3, + @"productId": @"com.yumi.coin100" +}; + +[[BuglyManager sharedManager] reportIAPError:@"user123" + transactionId:@"txn_123456" + orderId:@"order_789" + status:2 + context:context]; +``` + +## 重构完成情况 + +### ✅ 已完成 +1. 创建 `BuglyManager.h` 和 `BuglyManager.m` +2. 修改 `AppDelegate+ThirdConfig.m` 使用 BuglyManager +3. 修改 `IAPManager.m` 使用 BuglyManager +4. 修改 `HttpRequestHelper.m` 使用 BuglyManager +5. 修改 `GiftComboManager.m` 使用 BuglyManager +6. 创建使用示例和文档 + +### 🔄 进行中 +1. 修改 `XPGiftPresenter.m` 使用 BuglyManager + +### 📋 待完成 +1. 测试验证所有功能 +2. 完善卡顿通知逻辑 +3. 性能优化 + +## 优势 + +1. **统一管理**:所有 Bugly 相关操作集中在一个类中 +2. **降低耦合**:其他模块无需直接引入 Bugly 头文件 +3. **易于维护**:统一的接口和错误处理逻辑 +4. **功能扩展**:支持卡顿监听和自定义通知 +5. **向后兼容**:保持现有功能完全不变 + +## 注意事项 + +1. 确保在真机环境下编译,模拟器可能无法正确导入 Bugly 头文件 +2. 卡顿监听功能需要在实际设备上测试 +3. 错误上报是异步操作,不会阻塞主线程 +4. 建议在 AppDelegate 中尽早初始化 BuglyManager diff --git a/YuMi/Modules/YMMine/View/Recharge/IAPManager.m b/YuMi/Modules/YMMine/View/Recharge/IAPManager.m index 4bae4a8e..d16073e2 100644 --- a/YuMi/Modules/YMMine/View/Recharge/IAPManager.m +++ b/YuMi/Modules/YMMine/View/Recharge/IAPManager.m @@ -7,6 +7,7 @@ #import "IAPManager.h" #import +#import "BuglyManager.h" #import "Api+Mine.h" #import "YuMi-swift.h" #import "RechargeStorage.h" @@ -232,68 +233,23 @@ } - (void)_logToBugly:(NSString *)tid oID:(NSString *)oid status:(NSInteger)status { - - NSMutableDictionary *logDic = [NSMutableDictionary dictionary]; - // 安全处理交易ID - if ([NSString isEmpty:tid]) { - [logDic setObject:@"" forKey:@"内购 transactionId"]; - tid = @""; - } else { - [logDic setObject:tid forKey:@"内购 transactionId"]; - } - // 安全处理订单ID - if ([NSString isEmpty:oid]) { - [logDic setObject:@"" forKey:@"内购 orderId"]; - } else { - [logDic setObject:oid forKey:@"内购 orderId"]; - } - - // 安全获取用户ID + // 使用 BuglyManager 统一上报内购错误 NSString *uid = [AccountInfoStorage instance].getUid ?: @"未知用户"; - [logDic setObject:uid forKey:@"内购 用户id"]; - // 添加重试次数信息 - [logDic setObject:@([self getRetryCountForTransaction:tid]) forKey:@"重试次数"]; - [logDic setObject:@(self.recheckInterval) forKey:@"重试间隔"]; - [logDic setObject:@(self.recheckIndex) forKey:@"当前索引"]; - [logDic setObject:@(self.isProcessing) forKey:@"处理中状态"]; - [logDic setObject:@(self.isLogin) forKey:@"登录状态"]; + // 构建上下文信息 + NSMutableDictionary *context = [NSMutableDictionary dictionary]; + [context setObject:@([self getRetryCountForTransaction:tid]) forKey:@"重试次数"]; + [context setObject:@(self.recheckInterval) forKey:@"重试间隔"]; + [context setObject:@(self.recheckIndex) forKey:@"当前索引"]; + [context setObject:@(self.isProcessing) forKey:@"处理中状态"]; + [context setObject:@(self.isLogin) forKey:@"登录状态"]; - NSString *statusMsg = @""; - NSInteger code = -20000; - switch (status) { - case 0: - statusMsg = [NSString stringWithFormat:@"UID: %@, 尝试验单", uid]; - break; - case 1: - statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单成功", uid]; - code = -20001; - break; - case 2: - statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单失败", uid]; - code = -20002; - break; - case 3: - statusMsg = [NSString stringWithFormat:@"UID: %@, 验单-补单 id 异常", uid]; - code = -20002; - break; - case 4: - statusMsg = [NSString stringWithFormat:@"UID: %@, 重试次数过多", uid]; - code = -20003; - break; - case 5: - statusMsg = [NSString stringWithFormat:@"UID: %@, 过期交易清理", uid]; - code = -20004; - break; - default: - break; - } - - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - [Bugly reportError:[NSError errorWithDomain:statusMsg - code:code - userInfo:logDic]]; - }); + // 使用 BuglyManager 上报 + [[BuglyManager sharedManager] reportIAPError:uid + transactionId:tid + orderId:oid + status:status + context:context]; } // 内购成功并通知外部 diff --git a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m index 372e6135..5dfb1d58 100644 --- a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m +++ b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m @@ -11,6 +11,7 @@ #import #import #import +#import "BuglyManager.h" #import "Api+Gift.h" @@ -790,19 +791,17 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific self.errorMessage = [NSString stringWithFormat:@"服务器繁忙,请稍后重试 - %@", msg]; #else self.errorMessage = @"Over Heat & try later"; - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - NSMutableDictionary *logDic = [@{@"targetUids": allUIDs, - @"giftNum": self.giftNumPerTimes} mutableCopy]; - [logDic addEntriesFromDictionary:dic]; - [logDic setObject:[NSThread callStackSymbols] forKey:@"call stack symbols"]; - [logDic setObject:msg forKey:@"error message"]; - [logDic setObject:@"gift/sendV5" forKey:@"http method"]; - [Bugly reportError:[NSError errorWithDomain:[NSString stringWithFormat:@"UID: %@,API: %@ 异常", - [AccountInfoStorage instance].getUid, - @"gift/sendV5"] - code:code - userInfo:logDic]]; - }); + // 使用 BuglyManager 统一上报礼物发送错误 + NSString *uid = [AccountInfoStorage instance].getUid ?: @"未知用户"; + NSMutableDictionary *userInfo = [@{@"targetUids": allUIDs, + @"giftNum": self.giftNumPerTimes} mutableCopy]; + [userInfo addEntriesFromDictionary:dic]; + [userInfo setObject:msg forKey:@"error message"]; + + [[BuglyManager sharedManager] reportNetworkError:uid + api:@"gift/sendV5" + code:code + userInfo:userInfo]; #endif // 临时错误,不重置连击状态,允许用户重试 } else if (code == 31005) { diff --git a/YuMi/Modules/YMRoom/View/SendGiftView/Presenter/XPGiftPresenter.m b/YuMi/Modules/YMRoom/View/SendGiftView/Presenter/XPGiftPresenter.m index 91a5105f..4d74978f 100644 --- a/YuMi/Modules/YMRoom/View/SendGiftView/Presenter/XPGiftPresenter.m +++ b/YuMi/Modules/YMRoom/View/SendGiftView/Presenter/XPGiftPresenter.m @@ -20,6 +20,7 @@ ///P #import "XPGiftProtocol.h" #import +#import "BuglyManager.h" @interface XPGiftPresenter () /// diff --git a/YuMi/Network/HttpRequestHelper.m b/YuMi/Network/HttpRequestHelper.m index e676079a..29764659 100644 --- a/YuMi/Network/HttpRequestHelper.m +++ b/YuMi/Network/HttpRequestHelper.m @@ -14,6 +14,7 @@ #import "MSParamsDecode.h" #import "NSData+GZIP.h" #import +#import "BuglyManager.h" @implementation HttpRequestHelper @@ -409,18 +410,16 @@ constructingBodyWithBlock:^(id _Nonnull formData) { completion(nil, resCode, message); } if (resCode > 500 && resCode < 600) { - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - NSMutableDictionary *logDic = [params mutableCopy]; - [logDic setObject:[NSThread callStackSymbols] forKey:@"call stack symbols"]; - [logDic setObject:message forKey:@"error message"]; - [logDic setObject:@(method) forKey:@"http method"]; -// BLYLog(BuglyLogLevelWarn, @"%@", [logDic toJSONString]); - [Bugly reportError:[NSError errorWithDomain:[NSString stringWithFormat:@"UID: %@,API: %@ 异常", - [AccountInfoStorage instance].getUid, - path] - code:resCode - userInfo:logDic]]; - }); + // 使用 BuglyManager 统一上报网络错误 + NSString *uid = [AccountInfoStorage instance].getUid ?: @"未知用户"; + NSMutableDictionary *userInfo = [params mutableCopy]; + [userInfo setObject:message forKey:@"error message"]; + [userInfo setObject:@(method) forKey:@"http method"]; + + [[BuglyManager sharedManager] reportNetworkError:uid + api:path + code:resCode + userInfo:userInfo]; } }]; }