refactor: 更新 AppDelegate 和模块导入以简化配置管理
主要变更: 1. 移除不必要的模块导入,简化 AppDelegate 中的代码结构。 2. 引入新的 EPConfigManager 和 EPNIMManager,统一配置管理和 NIMSDK 初始化逻辑。 3. 更新相关方法以使用 block 回调,提升代码的可读性和维护性。 4. 新增 EPClientAPIBridge 和相关配置文件,增强项目的模块化。 此更新旨在提升代码的可维护性,减少冗余实现,确保配置管理的一致性。
This commit is contained in:
@@ -416,6 +416,12 @@
|
||||
4C1392962D6DA22B00A6DFB5 /* RechargerTransferHistoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1392952D6DA22B00A6DFB5 /* RechargerTransferHistoryViewController.m */; };
|
||||
4C13929D2D70441500A6DFB5 /* giftgift.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 4C13929B2D70441500A6DFB5 /* giftgift.mp4 */; };
|
||||
4C1392A12D71675900A6DFB5 /* coincoin.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 4C1392A02D71675900A6DFB5 /* coincoin.mp4 */; };
|
||||
4C14398D2EA62D3C0037B074 /* EPClientAPIBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C14398C2EA62D3C0037B074 /* EPClientAPIBridge.m */; };
|
||||
4C1439912EA62DD30037B074 /* EPConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C14398F2EA62DD30037B074 /* EPConfigManager.swift */; };
|
||||
4C1439922EA62DD30037B074 /* EPConfigStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1439902EA62DD30037B074 /* EPConfigStorage.m */; };
|
||||
4C1439942EA630490037B074 /* EPConfigAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1439932EA630490037B074 /* EPConfigAPI.swift */; };
|
||||
4C14399C2EA635EB0037B074 /* EPNIMConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1439972EA635EB0037B074 /* EPNIMConfig.m */; };
|
||||
4C14399D2EA635EB0037B074 /* EPNIMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1439992EA635EB0037B074 /* EPNIMManager.m */; };
|
||||
4C1892992CF84349004D4426 /* RoomCahtCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1892982CF84349004D4426 /* RoomCahtCell.m */; };
|
||||
4C1A141B2DCB4AB700B6D0CA /* ChatFaceVo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A141A2DCB4AB700B6D0CA /* ChatFaceVo.m */; };
|
||||
4C1E98BF2E9A3A540031AE79 /* EPMineAPIHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98BD2E9A3A540031AE79 /* EPMineAPIHelper.m */; };
|
||||
@@ -2478,6 +2484,16 @@
|
||||
4C1392952D6DA22B00A6DFB5 /* RechargerTransferHistoryViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RechargerTransferHistoryViewController.m; sourceTree = "<group>"; };
|
||||
4C13929B2D70441500A6DFB5 /* giftgift.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = giftgift.mp4; sourceTree = "<group>"; };
|
||||
4C1392A02D71675900A6DFB5 /* coincoin.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = coincoin.mp4; sourceTree = "<group>"; };
|
||||
4C14398B2EA62D3C0037B074 /* EPClientAPIBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPClientAPIBridge.h; sourceTree = "<group>"; };
|
||||
4C14398C2EA62D3C0037B074 /* EPClientAPIBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPClientAPIBridge.m; sourceTree = "<group>"; };
|
||||
4C14398E2EA62D8C0037B074 /* EPConfigStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPConfigStorage.h; sourceTree = "<group>"; };
|
||||
4C14398F2EA62DD30037B074 /* EPConfigManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPConfigManager.swift; sourceTree = "<group>"; };
|
||||
4C1439902EA62DD30037B074 /* EPConfigStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPConfigStorage.m; sourceTree = "<group>"; };
|
||||
4C1439932EA630490037B074 /* EPConfigAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPConfigAPI.swift; sourceTree = "<group>"; };
|
||||
4C1439962EA635EB0037B074 /* EPNIMConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPNIMConfig.h; sourceTree = "<group>"; };
|
||||
4C1439972EA635EB0037B074 /* EPNIMConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPNIMConfig.m; sourceTree = "<group>"; };
|
||||
4C1439982EA635EB0037B074 /* EPNIMManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPNIMManager.h; sourceTree = "<group>"; };
|
||||
4C1439992EA635EB0037B074 /* EPNIMManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPNIMManager.m; sourceTree = "<group>"; };
|
||||
4C1892972CF84349004D4426 /* RoomCahtCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomCahtCell.h; sourceTree = "<group>"; };
|
||||
4C1892982CF84349004D4426 /* RoomCahtCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomCahtCell.m; sourceTree = "<group>"; };
|
||||
4C1A14192DCB4AB700B6D0CA /* ChatFaceVo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChatFaceVo.h; sourceTree = "<group>"; };
|
||||
@@ -6465,6 +6481,7 @@
|
||||
4C0642922E98EF0A00BAF413 /* E-P */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C14399B2EA635EB0037B074 /* SDKManager */,
|
||||
4C59C0FC2EA2508F00D1F7BD /* NewMessage */,
|
||||
4CD19C852E9CB31C0069DAA0 /* NewLogin */,
|
||||
4C1E98C22E9A45160031AE79 /* Common */,
|
||||
@@ -6485,6 +6502,25 @@
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4C14399A2EA635EB0037B074 /* NIMSDK */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C1439962EA635EB0037B074 /* EPNIMConfig.h */,
|
||||
4C1439972EA635EB0037B074 /* EPNIMConfig.m */,
|
||||
4C1439982EA635EB0037B074 /* EPNIMManager.h */,
|
||||
4C1439992EA635EB0037B074 /* EPNIMManager.m */,
|
||||
);
|
||||
path = NIMSDK;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4C14399B2EA635EB0037B074 /* SDKManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C14399A2EA635EB0037B074 /* NIMSDK */,
|
||||
);
|
||||
path = SDKManager;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4C1E98BE2E9A3A540031AE79 /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -6497,6 +6533,12 @@
|
||||
4C1E98C22E9A45160031AE79 /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4C1439932EA630490037B074 /* EPConfigAPI.swift */,
|
||||
4C14398F2EA62DD30037B074 /* EPConfigManager.swift */,
|
||||
4C1439902EA62DD30037B074 /* EPConfigStorage.m */,
|
||||
4C14398E2EA62D8C0037B074 /* EPConfigStorage.h */,
|
||||
4C14398B2EA62D3C0037B074 /* EPClientAPIBridge.h */,
|
||||
4C14398C2EA62D3C0037B074 /* EPClientAPIBridge.m */,
|
||||
4C1E98C72E9A4DFD0031AE79 /* EPQCloudConfig.swift */,
|
||||
4C1E98C82E9A4DFD0031AE79 /* EPSDKManager.swift */,
|
||||
4C1E98C02E9A45160031AE79 /* EPImageUploader.swift */,
|
||||
@@ -12526,6 +12568,9 @@
|
||||
4C1A141B2DCB4AB700B6D0CA /* ChatFaceVo.m in Sources */,
|
||||
E8664ED627E434D5000171BA /* XPRoomPKRecordViewController.m in Sources */,
|
||||
E87E914E2796678D00A7B3F2 /* XPMineDressEmptyTableViewCell.m in Sources */,
|
||||
4C14398D2EA62D3C0037B074 /* EPClientAPIBridge.m in Sources */,
|
||||
4C14399C2EA635EB0037B074 /* EPNIMConfig.m in Sources */,
|
||||
4C14399D2EA635EB0037B074 /* EPNIMManager.m in Sources */,
|
||||
232EBBFF2BD7A25500E8CEAD /* MSParamsDecode.m in Sources */,
|
||||
9B7D804D27537950003DAC0C /* MessageCell.m in Sources */,
|
||||
23E9EAA62A84C97C00B792F2 /* XPMineUserInfoTagVC.m in Sources */,
|
||||
@@ -12849,6 +12894,7 @@
|
||||
E8751E5928A62A390056EF44 /* Api+Sailing.m in Sources */,
|
||||
E897ABFF28AF39B4003B3587 /* XPSailingAnimationView.m in Sources */,
|
||||
E885D5362977CE28004DC088 /* SessionSettingModel.m in Sources */,
|
||||
4C1439942EA630490037B074 /* EPConfigAPI.swift in Sources */,
|
||||
9BE01AE128937DBC00B50299 /* XPDressUpShopCardViewController.m in Sources */,
|
||||
E896EFA22771AE9400AD2CC1 /* XPMineFriendViewController.m in Sources */,
|
||||
1427218D29A75F6F00C7C423 /* HTTPRedirectResponse.m in Sources */,
|
||||
@@ -13108,6 +13154,8 @@
|
||||
2331C1742A5EB71000E1D940 /* XPNobleCenterResidueView.m in Sources */,
|
||||
4C0A5B842E02675300955219 /* MedalsCollectionViewCell.m in Sources */,
|
||||
E80E2377299A47F60013FD40 /* AESUtils.m in Sources */,
|
||||
4C1439912EA62DD30037B074 /* EPConfigManager.swift in Sources */,
|
||||
4C1439922EA62DD30037B074 /* EPConfigStorage.m in Sources */,
|
||||
E81060E229876E9100B772F0 /* MessageImageModel.m in Sources */,
|
||||
E839533F276A0CDB00CF2F24 /* XPMineNameplateTableViewCell.m in Sources */,
|
||||
E80E09AE2A41336500CD2BE7 /* XPWebViewNavView.m in Sources */,
|
||||
|
@@ -7,21 +7,16 @@
|
||||
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "TabbarViewController.h"
|
||||
#import "BaseNavigationController.h"
|
||||
#import "AppDelegate+ThirdConfig.h"
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
#import <AppTrackingTransparency/AppTrackingTransparency.h>
|
||||
#import "ClientConfig.h"
|
||||
#import "LoginViewController.h"
|
||||
#import "AccountModel.h"
|
||||
#import "YuMi-swift.h"
|
||||
#import "SessionViewController.h"
|
||||
#import "LoginFullInfoViewController.h"
|
||||
#import "UIView+VAP.h"
|
||||
#import "SocialShareManager.h"
|
||||
#import "EPSignatureColorGuideView.h"
|
||||
#import "EPEmotionColorStorage.h"
|
||||
#import "EPNIMManager.h"
|
||||
|
||||
UIKIT_EXTERN NSString * const kOpenRoomNotification;
|
||||
|
||||
@@ -62,17 +57,28 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
|
||||
[VAPView registerHWDLog:qg_VAP_Logger_handler];
|
||||
|
||||
///初始化一些 sdk配置
|
||||
[self initThirdConfig];
|
||||
[self initUM:application launchOptions:launchOptions];
|
||||
|
||||
// 冷启动配置:client/init → client/config,由 EPConfigManager 统一调度
|
||||
@kWeakify(self);
|
||||
[[ClientConfig shareConfig] clientConfig:^{
|
||||
@kStrongify(self);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[EPConfigManager shared] startColdBootWithOnSuccess:^{
|
||||
// 配置成功,初始化 NIMSDK 并进入主页面
|
||||
[[EPNIMManager sharedManager] initializeWithCompletion:^(NSError * _Nullable error) {
|
||||
@kStrongify(self);
|
||||
if (error) {
|
||||
NSLog(@"[AppDelegate] NIMSDK 初始化失败: %@", error);
|
||||
} else {
|
||||
NSLog(@"[AppDelegate] NIMSDK 初始化成功");
|
||||
}
|
||||
// 无论 NIMSDK 是否成功,都进入主页面
|
||||
[self loadMainPage];
|
||||
[self setupLaunchADView];
|
||||
});
|
||||
}];
|
||||
} onFailure:^(NSString * _Nonnull errorMessage) {
|
||||
@kStrongify(self);
|
||||
// 配置失败,显示错误提示
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:YMLocalizedString(@"提示")
|
||||
message:errorMessage
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:YMLocalizedString(@"确定") style:UIAlertActionStyleDefault handler:nil]];
|
||||
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||
}];
|
||||
|
||||
if (@available(iOS 15, *)) {
|
||||
@@ -84,11 +90,6 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
|
||||
// MARK: - Helper Methods
|
||||
|
||||
- (void)initUM:(UIApplication *)application
|
||||
launchOptions:(NSDictionary *)launchOptions {
|
||||
// MobLink 已移除
|
||||
}
|
||||
|
||||
- (void)loadMainPage {
|
||||
AccountModel *accountModel = [[AccountInfoStorage instance] getCurrentAccountInfo];
|
||||
if (accountModel == nil ||
|
||||
@@ -103,10 +104,10 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
[self checkAndShowSignatureColorGuide];
|
||||
});
|
||||
}
|
||||
|
||||
[[ClientConfig shareConfig] clientInit];
|
||||
}
|
||||
|
||||
// 移除 EPConfig 通知相关方法,改用 block 回调
|
||||
|
||||
/// 检查并显示专属颜色引导页
|
||||
- (void)checkAndShowSignatureColorGuide {
|
||||
UIWindow *keyWindow = kWindow;
|
||||
@@ -114,7 +115,7 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
|
||||
BOOL hasSignatureColor = [EPEmotionColorStorage hasUserSignatureColor];
|
||||
|
||||
#if DEBUG
|
||||
#if 0
|
||||
// Debug 环境:总是显示引导页
|
||||
NSLog(@"[AppDelegate] Debug 模式:显示专属颜色引导页(已有颜色: %@)", hasSignatureColor ? @"YES" : @"NO");
|
||||
|
||||
@@ -156,16 +157,9 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
[[BaseNavigationController alloc] initWithRootViewController:lvc];
|
||||
navigationController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
self.window.rootViewController = navigationController;
|
||||
|
||||
// 旧代码保留注释(便于回滚)
|
||||
// LoginViewController *lvc = [[LoginViewController alloc] init];
|
||||
// BaseNavigationController * navigationController = [[BaseNavigationController alloc] initWithRootViewController:lvc];
|
||||
// navigationController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
// self.window.rootViewController = navigationController;
|
||||
}
|
||||
|
||||
- (void)toHomeTabbarPage {
|
||||
// ========== 白牌版本:使用新的 EPTabBarController ==========
|
||||
EPTabBarController *epTabBar = [EPTabBarController create];
|
||||
[epTabBar refreshTabBarWithIsLogin:YES];
|
||||
|
||||
@@ -174,19 +168,10 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
window.rootViewController = epTabBar;
|
||||
[window makeKeyAndVisible];
|
||||
}
|
||||
|
||||
NSLog(@"[AppDelegate] 自动登录后已切换到白牌 TabBar:EPTabBarController");
|
||||
|
||||
// ========== 原代码(已注释) ==========
|
||||
/*
|
||||
TabbarViewController *vc = [[TabbarViewController alloc] init];
|
||||
BaseNavigationController *navigationController = [[BaseNavigationController alloc] initWithRootViewController:vc];
|
||||
self.window.rootViewController = navigationController;
|
||||
*/
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
NSInteger count = [NIMSDK sharedSDK].conversationManager.allUnreadCount;
|
||||
NSInteger count = [[EPNIMManager sharedManager] allUnreadCount];
|
||||
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
|
||||
}
|
||||
|
||||
@@ -222,8 +207,8 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
||||
// 上传devicetoken至云信服务器。
|
||||
[[NIMSDK sharedSDK] updateApnsToken:deviceToken ];
|
||||
// 上传 deviceToken 至云信服务器(统一走 EPNIMManager)
|
||||
[[EPNIMManager sharedManager] updateApnsToken:deviceToken];
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
|
||||
@@ -255,45 +240,10 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
|
||||
|
||||
///URL Scheme跳转
|
||||
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
|
||||
// TODO: 在 EPTabbar 中补充 [SocialShareManager sharedManager] setHandleJumpToRoom
|
||||
[[SocialShareManager sharedManager] handleURL:url];
|
||||
return YES;
|
||||
}
|
||||
|
||||
//- (void)__oldApplicationOpenURLMethod:(NSURL *)url {
|
||||
// NSString *text = [url query];
|
||||
// if(text.length){
|
||||
// NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary];
|
||||
// NSArray *paramArray = [text componentsSeparatedByString:@"&"];
|
||||
// for (NSString *param in paramArray) {
|
||||
// if (param && param.length) {
|
||||
// NSArray *parArr = [param componentsSeparatedByString:@"="];
|
||||
// if (parArr.count == 2) {
|
||||
// [paramsDict setObject:parArr[1] forKey:parArr[0]];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if(paramsDict[@"type"] != nil){
|
||||
// NSInteger type = [paramsDict[@"type"] integerValue];
|
||||
// if (type == 2) {
|
||||
// NSString *uid = [NSString stringWithFormat:@"%@",paramsDict[@"uid"]];
|
||||
// [[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"uid":uid}];
|
||||
// ClientConfig *config = [ClientConfig shareConfig];
|
||||
// config.roomId = uid;
|
||||
// }else if(type == 7){
|
||||
// NSString *uid = [NSString stringWithFormat:@"%@",paramsDict[@"uid"]];
|
||||
// [[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"type":@"kOpenChat",@"uid":uid}];
|
||||
// ClientConfig *config = [ClientConfig shareConfig];
|
||||
// config.chatId = uid;
|
||||
// }else if (type == 8){
|
||||
// NSString *inviteCode = paramsDict[@"inviteCode"];
|
||||
// if (inviteCode != nil && [[AccountInfoStorage instance]getUid].length == 0){
|
||||
// ClientConfig *config = [ClientConfig shareConfig];
|
||||
// config.inviteCode = inviteCode;
|
||||
// }
|
||||
// }
|
||||
//// return YES;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@end
|
||||
|
26
YuMi/E-P/Common/EPClientAPIBridge.h
Normal file
26
YuMi/E-P/Common/EPClientAPIBridge.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// EPClientAPIBridge.h
|
||||
// YuMi
|
||||
//
|
||||
// Deprecated: replaced by Swift EPConfigAPI
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Bridge to wrap existing Objective-C APIs for Swift consumers
|
||||
__attribute__((deprecated("Use EPConfigAPI (Swift) instead")))
|
||||
@interface EPClientAPIBridge : NSObject
|
||||
|
||||
/// Call Api.clientInitConfig and forward raw dictionary and status
|
||||
+ (void)clientInit:(void(^)(NSDictionary * _Nullable data, NSInteger code, NSString * _Nullable msg))completion;
|
||||
|
||||
/// Call ClientConfig.clientConfig; returns code 200 on success (no payload)
|
||||
+ (void)clientConfig:(void(^)(NSDictionary * _Nullable data, NSInteger code, NSString * _Nullable msg))completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
36
YuMi/E-P/Common/EPClientAPIBridge.m
Normal file
36
YuMi/E-P/Common/EPClientAPIBridge.m
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// EPClientAPIBridge.m
|
||||
// YuMi
|
||||
//
|
||||
// Objective-C to Swift bridge for client init/config APIs
|
||||
//
|
||||
|
||||
#import "EPClientAPIBridge.h"
|
||||
#import "Api+Main.h"
|
||||
#import "ClientConfig.h"
|
||||
#import "BaseModel.h"
|
||||
|
||||
@implementation EPClientAPIBridge
|
||||
|
||||
+ (void)clientInit:(void(^)(NSDictionary * _Nullable data, NSInteger code, NSString * _Nullable msg))completion {
|
||||
if (!completion) { return; }
|
||||
[Api clientInitConfig:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||||
NSDictionary *payload = nil;
|
||||
if (code == 200 && data.data && [data.data isKindOfClass:[NSDictionary class]]) {
|
||||
payload = (NSDictionary *)data.data;
|
||||
}
|
||||
completion(payload, code, msg);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)clientConfig:(void(^)(NSDictionary * _Nullable data, NSInteger code, NSString * _Nullable msg))completion {
|
||||
if (!completion) { return; }
|
||||
// ClientConfig.clientConfig only has a finish block with no parameters; treat success as code 200
|
||||
[[ClientConfig shareConfig] clientConfig:^{
|
||||
completion(nil, 200, nil);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
37
YuMi/E-P/Common/EPConfigAPI.swift
Normal file
37
YuMi/E-P/Common/EPConfigAPI.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// EPConfigAPI.swift
|
||||
// YuMi
|
||||
//
|
||||
// Thin Swift wrapper aligning EP module naming, for client/init & client/config
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc final class EPConfigAPI: NSObject {
|
||||
|
||||
/// GET client/init — returns payload dictionary when code == 200
|
||||
@objc static func clientInit(
|
||||
completion: @escaping (_ data: [String: Any]?, _ code: Int, _ msg: String?) -> Void
|
||||
) {
|
||||
Api.clientInitConfig { baseModel, code, msg in
|
||||
var dict: [String: Any]? = nil
|
||||
if code == 200, let payload = baseModel?.data as? [String: Any] {
|
||||
dict = payload
|
||||
}
|
||||
completion(dict, Int(code), msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// GET client/config — treat success as code 200 (no payload)
|
||||
@objc static func clientConfig(
|
||||
completion: @escaping (_ data: [String: Any]?, _ code: Int, _ msg: String?) -> Void
|
||||
) {
|
||||
// ClientConfig has + (instancetype)shareConfig; bridged to Swift as .share()
|
||||
// If the symbol differs, adjust to your Swift name (e.g., shareConfig()).
|
||||
ClientConfig.share().clientConfig {
|
||||
completion(nil, 200, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
133
YuMi/E-P/Common/EPConfigManager.swift
Normal file
133
YuMi/E-P/Common/EPConfigManager.swift
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// EPConfigManager.swift
|
||||
// YuMi
|
||||
//
|
||||
// Cold boot configuration manager for client/init and client/config flows
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc final class EPConfigManager: NSObject {
|
||||
@objc static let shared = EPConfigManager()
|
||||
|
||||
// MARK: - State
|
||||
@objc private(set) var isInitReady: Bool = false
|
||||
@objc private(set) var isConfigReady: Bool = false
|
||||
@objc private(set) var isUsingPersistedInit: Bool = false
|
||||
|
||||
// 原始数据(向后兼容)
|
||||
@objc private(set) var initModelRaw: [String: Any]? = nil
|
||||
@objc private(set) var configModelRaw: [String: Any]? = nil
|
||||
|
||||
// 强类型模型
|
||||
@objc private(set) var clientDataModel: ClientDataModel? = nil
|
||||
|
||||
private var hasStarted = false
|
||||
|
||||
// 回调闭包
|
||||
private var successCallback: (() -> Void)?
|
||||
private var failureCallback: ((String) -> Void)?
|
||||
|
||||
// MARK: - Public API
|
||||
@objc(startColdBootWithOnSuccess:onFailure:)
|
||||
func startColdBoot(
|
||||
onSuccess: @escaping () -> Void,
|
||||
onFailure: @escaping (String) -> Void
|
||||
) {
|
||||
guard !hasStarted else {
|
||||
// 如果已经启动过,根据当前状态直接回调
|
||||
if isInitReady && isConfigReady {
|
||||
onSuccess()
|
||||
} else if !isInitReady {
|
||||
onFailure("配置初始化失败")
|
||||
}
|
||||
return
|
||||
}
|
||||
hasStarted = true
|
||||
|
||||
// 保存回调
|
||||
self.successCallback = onSuccess
|
||||
self.failureCallback = onFailure
|
||||
|
||||
runClientInitWithRetry(maxRetry: 5, interval: 1.0)
|
||||
}
|
||||
|
||||
// MARK: - Flow
|
||||
private func runClientInitWithRetry(maxRetry: Int, interval: TimeInterval) {
|
||||
attemptClientInit(remaining: maxRetry, interval: interval)
|
||||
}
|
||||
|
||||
private func attemptClientInit(remaining: Int, interval: TimeInterval) {
|
||||
EPConfigAPI.clientInit { [weak self] data, code, msg in
|
||||
guard let self = self else { return }
|
||||
if code == 200, let dict = data {
|
||||
self.onInitSuccess(dict)
|
||||
self.runClientConfig()
|
||||
} else if remaining > 0 {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
|
||||
self.attemptClientInit(remaining: remaining - 1, interval: interval)
|
||||
}
|
||||
} else {
|
||||
self.onInitExhausted()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func onInitSuccess(_ dict: [String: Any]) {
|
||||
// 1. 转换为强类型模型
|
||||
let model = ClientDataModel.model(withJSON: dict)
|
||||
self.clientDataModel = model
|
||||
|
||||
// 2. 更新 ClientConfig(保持现有代码兼容)
|
||||
ClientConfig.share().configInfo = model
|
||||
|
||||
// 3. 持久化原始字典(避免模型变更时数据失效)
|
||||
_ = EPConfigStorage.saveInit(dict)
|
||||
|
||||
// 4. 更新状态
|
||||
isUsingPersistedInit = false
|
||||
initModelRaw = dict
|
||||
isInitReady = true
|
||||
|
||||
// 5. 继续执行 client/config
|
||||
runClientConfig()
|
||||
}
|
||||
|
||||
private func onInitExhausted() {
|
||||
if let persistedDict = EPConfigStorage.loadInit() as? [String: Any] {
|
||||
// 使用持久化数据
|
||||
let model = ClientDataModel.model(withJSON: persistedDict)
|
||||
self.clientDataModel = model
|
||||
ClientConfig.share().configInfo = model
|
||||
|
||||
isUsingPersistedInit = true
|
||||
initModelRaw = persistedDict
|
||||
isInitReady = true
|
||||
|
||||
// 尝试获取最新配置
|
||||
runClientConfig()
|
||||
} else {
|
||||
// 无持久化数据,调用失败回调
|
||||
failureCallback?("网络异常,请稍后重新启动应用")
|
||||
}
|
||||
}
|
||||
|
||||
private func runClientConfig() {
|
||||
EPConfigAPI.clientConfig { [weak self] data, code, msg in
|
||||
guard let self = self else { return }
|
||||
if code == 200 {
|
||||
// client/config 成功,标记完成并调用成功回调
|
||||
self.isConfigReady = true
|
||||
self.successCallback?()
|
||||
} else {
|
||||
// client/config 失败,但 init 已成功,仍可继续
|
||||
self.isConfigReady = true
|
||||
self.successCallback?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除 Notification 扩展,不再需要
|
||||
|
||||
|
27
YuMi/E-P/Common/EPConfigStorage.h
Normal file
27
YuMi/E-P/Common/EPConfigStorage.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// EPConfigStorage.h
|
||||
// YuMi
|
||||
//
|
||||
// Lightweight persistence for client/init data
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface EPConfigStorage : NSObject
|
||||
|
||||
/// Save init payload dictionary to disk (Application Support)
|
||||
+ (BOOL)saveInit:(NSDictionary *)dict;
|
||||
|
||||
/// Load init payload dictionary from disk; returns nil if missing/invalid
|
||||
+ (NSDictionary * _Nullable)loadInit;
|
||||
|
||||
/// Remove persisted init payload
|
||||
+ (BOOL)clearInit;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
62
YuMi/E-P/Common/EPConfigStorage.m
Normal file
62
YuMi/E-P/Common/EPConfigStorage.m
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// EPConfigStorage.m
|
||||
// YuMi
|
||||
//
|
||||
// Lightweight persistence for client/init data
|
||||
//
|
||||
|
||||
#import "EPConfigStorage.h"
|
||||
|
||||
@implementation EPConfigStorage
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
+ (BOOL)saveInit:(NSDictionary *)dict {
|
||||
if (![dict isKindOfClass:[NSDictionary class]]) { return NO; }
|
||||
NSMutableDictionary *wrapped = [dict mutableCopy];
|
||||
wrapped[@"_version"] = @1;
|
||||
wrapped[@"_timestamp"] = @((long long)([[NSDate date] timeIntervalSince1970]));
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:wrapped options:0 error:nil];
|
||||
if (!data) { return NO; }
|
||||
NSString *path = [self initPath];
|
||||
NSError *error = nil;
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSString *dir = [path stringByDeletingLastPathComponent];
|
||||
if (![fm fileExistsAtPath:dir]) {
|
||||
[fm createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:&error];
|
||||
if (error) { return NO; }
|
||||
}
|
||||
return [data writeToFile:path atomically:YES];
|
||||
}
|
||||
|
||||
+ (NSDictionary * _Nullable)loadInit {
|
||||
NSString *path = [self initPath];
|
||||
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||
if (!data) { return nil; }
|
||||
id obj = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
||||
if (![obj isKindOfClass:[NSDictionary class]]) { return nil; }
|
||||
return (NSDictionary *)obj;
|
||||
}
|
||||
|
||||
+ (BOOL)clearInit {
|
||||
NSString *path = [self initPath];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if (![fm fileExistsAtPath:path]) { return YES; }
|
||||
NSError *error = nil;
|
||||
[fm removeItemAtPath:path error:&error];
|
||||
return (error == nil);
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
+ (NSString *)initPath {
|
||||
NSArray<NSURL *> *urls = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask];
|
||||
NSURL *dirURL = urls.firstObject;
|
||||
if (!dirURL) { dirURL = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) firstObject]]; }
|
||||
NSURL *fileURL = [dirURL URLByAppendingPathComponent:@"ep_config_init.json"];
|
||||
return fileURL.path;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
27
YuMi/E-P/Common/EPSDKManager+NIM.swift
Normal file
27
YuMi/E-P/Common/EPSDKManager+NIM.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// EPSDKManager+NIM.swift
|
||||
// YuMi
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc extension EPSDKManager {
|
||||
/// 初始化 NIMSDK(从 ClientConfig 获取 nimKey)
|
||||
@objc func initializeNIMSDK(completion: ((NSError?) -> Void)? = nil) {
|
||||
EPNIMManager.shared().initialize { error in
|
||||
completion?(error as NSError?)
|
||||
}
|
||||
}
|
||||
|
||||
/// 上传 APNS token 到 NIM
|
||||
@objc func updateNIMApnsToken(_ deviceToken: Data) {
|
||||
EPNIMManager.shared().updateApnsToken(deviceToken)
|
||||
}
|
||||
|
||||
/// 获取 NIM 未读数
|
||||
@objc func nimUnreadCount() -> Int {
|
||||
return Int(EPNIMManager.shared().allUnreadCount())
|
||||
}
|
||||
}
|
||||
|
||||
|
29
YuMi/E-P/SDKManager/NIMSDK/EPNIMConfig.h
Normal file
29
YuMi/E-P/SDKManager/NIMSDK/EPNIMConfig.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// EPNIMConfig.h
|
||||
// YuMi
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// NIMSDK 配置模型(从 ClientConfig 派生)
|
||||
@interface EPNIMConfig : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *appKey;
|
||||
@property (nonatomic, copy) NSString *apnsCername;
|
||||
@property (nonatomic, assign) BOOL shouldConsiderRevokedMessageUnreadCount;
|
||||
@property (nonatomic, assign) BOOL shouldSyncStickTopSessionInfos;
|
||||
@property (nonatomic, assign) BOOL enabledHttpsForInfo;
|
||||
@property (nonatomic, assign) BOOL enabledHttpsForMessage;
|
||||
@property (nonatomic, assign) NSInteger cdnTrackInterval;
|
||||
@property (nonatomic, assign) NSInteger chatroomMessageReceiveMinInterval;
|
||||
|
||||
/// 从 ClientConfig 创建配置;若缺失 nimKey 则返回 nil
|
||||
+ (instancetype _Nullable)configFromClientConfig;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
39
YuMi/E-P/SDKManager/NIMSDK/EPNIMConfig.m
Normal file
39
YuMi/E-P/SDKManager/NIMSDK/EPNIMConfig.m
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// EPNIMConfig.m
|
||||
// YuMi
|
||||
//
|
||||
|
||||
#import "EPNIMConfig.h"
|
||||
#import "ClientConfig.h"
|
||||
#import "YUMIConstant.h"
|
||||
|
||||
@implementation EPNIMConfig
|
||||
|
||||
+ (instancetype _Nullable)configFromClientConfig {
|
||||
ClientConfig *client = [ClientConfig shareConfig];
|
||||
if (client.configInfo == nil) {
|
||||
return nil;
|
||||
}
|
||||
NSString *nimKey = client.configInfo.nimKey;
|
||||
if (nimKey.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
EPNIMConfig *cfg = [[EPNIMConfig alloc] init];
|
||||
cfg.appKey = nimKey;
|
||||
#ifdef DEBUG
|
||||
cfg.apnsCername = @"pikoDevelopPush";
|
||||
#else
|
||||
cfg.apnsCername = @"newPiko";
|
||||
#endif
|
||||
cfg.shouldConsiderRevokedMessageUnreadCount = YES;
|
||||
cfg.shouldSyncStickTopSessionInfos = YES;
|
||||
cfg.enabledHttpsForInfo = YES;
|
||||
cfg.enabledHttpsForMessage = YES;
|
||||
cfg.cdnTrackInterval = 0;
|
||||
cfg.chatroomMessageReceiveMinInterval = 50;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
26
YuMi/E-P/SDKManager/NIMSDK/EPNIMManager.h
Normal file
26
YuMi/E-P/SDKManager/NIMSDK/EPNIMManager.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// EPNIMManager.h
|
||||
// YuMi
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface EPNIMManager : NSObject
|
||||
|
||||
+ (instancetype)sharedManager;
|
||||
|
||||
- (void)initializeWithCompletion:(void(^ _Nullable)(NSError * _Nullable error))completion;
|
||||
|
||||
- (void)updateApnsToken:(NSData *)deviceToken;
|
||||
|
||||
- (NSInteger)allUnreadCount;
|
||||
|
||||
- (BOOL)isInitialized;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
61
YuMi/E-P/SDKManager/NIMSDK/EPNIMManager.m
Normal file
61
YuMi/E-P/SDKManager/NIMSDK/EPNIMManager.m
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// EPNIMManager.m
|
||||
// YuMi
|
||||
//
|
||||
|
||||
#import "EPNIMManager.h"
|
||||
#import "EPNIMConfig.h"
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
#import "CustomAttachmentDecoder.h"
|
||||
|
||||
@interface EPNIMManager ()
|
||||
@property (nonatomic, assign) BOOL initialized;
|
||||
@end
|
||||
|
||||
@implementation EPNIMManager
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
static EPNIMManager *s;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{ s = [EPNIMManager new]; });
|
||||
return s;
|
||||
}
|
||||
|
||||
- (void)initializeWithCompletion:(void(^ _Nullable)(NSError * _Nullable error))completion {
|
||||
if (self.initialized) {
|
||||
if (completion) completion(nil);
|
||||
return;
|
||||
}
|
||||
EPNIMConfig *cfg = [EPNIMConfig configFromClientConfig];
|
||||
if (!cfg) {
|
||||
if (completion) {
|
||||
completion([NSError errorWithDomain:@"EPNIM" code:-1001 userInfo:@{NSLocalizedDescriptionKey:@"ClientConfig not ready or nimKey missing"}]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NIMSDKOption *option = [NIMSDKOption optionWithAppKey:cfg.appKey];
|
||||
option.apnsCername = cfg.apnsCername;
|
||||
[[NIMSDK sharedSDK] registerWithOption:option];
|
||||
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];
|
||||
[NIMSDKConfig sharedConfig].shouldConsiderRevokedMessageUnreadCount = cfg.shouldConsiderRevokedMessageUnreadCount;
|
||||
[[NIMSDKConfig sharedConfig] setShouldSyncStickTopSessionInfos:cfg.shouldSyncStickTopSessionInfos];
|
||||
[NIMSDKConfig sharedConfig].enabledHttpsForInfo = cfg.enabledHttpsForInfo;
|
||||
[NIMSDKConfig sharedConfig].enabledHttpsForMessage = cfg.enabledHttpsForMessage;
|
||||
[NIMSDKConfig sharedConfig].cdnTrackInterval = cfg.cdnTrackInterval;
|
||||
[NIMSDKConfig sharedConfig].chatroomMessageReceiveMinInterval = cfg.chatroomMessageReceiveMinInterval;
|
||||
self.initialized = YES;
|
||||
if (completion) completion(nil);
|
||||
}
|
||||
|
||||
- (void)updateApnsToken:(NSData *)deviceToken {
|
||||
if (!deviceToken) return;
|
||||
[[NIMSDK sharedSDK] updateApnsToken:deviceToken];
|
||||
}
|
||||
|
||||
- (NSInteger)allUnreadCount { return [NIMSDK sharedSDK].conversationManager.allUnreadCount; }
|
||||
|
||||
- (BOOL)isInitialized { return self.initialized; }
|
||||
|
||||
@end
|
||||
|
||||
|
@@ -20,8 +20,7 @@
|
||||
/// 初始化配置
|
||||
/// @param complection 完成
|
||||
+ (void)clientInitConfig:(HttpRequestHelperCompletion)complection {
|
||||
NSString * fang = [NSString stringFromBase64String:@"Y2xpZW50L2luaXQ="];///client/init
|
||||
[HttpRequestHelper request:fang method:HttpRequestHelperMethodGET params:@{} completion:complection];
|
||||
[HttpRequestHelper request:@"client/init" method:HttpRequestHelperMethodGET params:@{} completion:complection];
|
||||
}
|
||||
|
||||
+ (void)clientConfig:(HttpRequestHelperCompletion)completion {
|
||||
|
@@ -16,7 +16,8 @@
|
||||
// MARK: - Foundation
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
// MARK: - New Modules (White Label)
|
||||
// MARK: - New Modules
|
||||
#import "EPConfigStorage.h"
|
||||
#import "EPMomentViewController.h"
|
||||
#import "EPMineViewController.h"
|
||||
#import "EPMomentCell.h"
|
||||
@@ -78,6 +79,7 @@
|
||||
|
||||
// MARK: - Login - Captcha & Config
|
||||
#import "ClientConfig.h"
|
||||
#import "ClientDataModel.h"
|
||||
#import "TTPopup.h"
|
||||
|
||||
// 注意:
|
||||
|
Reference in New Issue
Block a user