5
This commit is contained in:
@@ -10,6 +10,6 @@
|
|||||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
@property (nonatomic, strong) UIWindow *window;
|
@property (nonatomic, strong) UIWindow *window;
|
||||||
- (void)setupRootVC;
|
- (void)toMainTabbarVC;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -94,13 +94,20 @@
|
|||||||
[self.window makeKeyAndVisible];
|
[self.window makeKeyAndVisible];
|
||||||
|
|
||||||
// 根据当前是否已登录决定入口:有 token 进主 TabBar,否则先进入登录页
|
// 根据当前是否已登录决定入口:有 token 进主 TabBar,否则先进入登录页
|
||||||
BOOL loggedIn = [[KBUserSessionManager shared] isLoggedIn];
|
// BOOL loggedIn = [[KBUserSessionManager shared] isLoggedIn];
|
||||||
UIViewController *rootVC = nil;
|
UIViewController *rootVC = nil;
|
||||||
if (loggedIn) {
|
|
||||||
rootVC = [[BaseTabBarController alloc] init];
|
rootVC = [[BaseTabBarController alloc] init];
|
||||||
} else {
|
|
||||||
rootVC = [[KBLoginVC alloc] init];
|
self.window.rootViewController = rootVC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)toMainTabbarVC{
|
||||||
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
|
self.window.backgroundColor = [UIColor whiteColor];
|
||||||
|
[self.window makeKeyAndVisible];
|
||||||
|
UIViewController *rootVC = nil;
|
||||||
|
rootVC = [[BaseTabBarController alloc] init];
|
||||||
self.window.rootViewController = rootVC;
|
self.window.rootViewController = rootVC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,35 +216,37 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)goLogin{
|
- (void)goLogin{
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
KBLoginVC *vc = [[KBLoginVC alloc] init];
|
||||||
KBLoginPopView *view = [[KBLoginPopView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, KB_SCREEN_WIDTH)];
|
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||||
// 创建并弹出
|
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
LSTPopView *pop = [LSTPopView initWithCustomView:view
|
// KBLoginPopView *view = [[KBLoginPopView alloc] initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, KB_SCREEN_WIDTH)];
|
||||||
parentView:nil
|
// // 创建并弹出
|
||||||
popStyle:LSTPopStyleSmoothFromBottom
|
// LSTPopView *pop = [LSTPopView initWithCustomView:view
|
||||||
dismissStyle:LSTDismissStyleSmoothToBottom];
|
// parentView:nil
|
||||||
pop.hemStyle = LSTHemStyleBottom;
|
// popStyle:LSTPopStyleSmoothFromBottom
|
||||||
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
// dismissStyle:LSTDismissStyleSmoothToBottom];
|
||||||
pop.isClickBgDismiss = YES; // 点击背景关闭
|
// pop.hemStyle = LSTHemStyleBottom;
|
||||||
pop.cornerRadius = 0; // 自定义 view 自处理圆角
|
// pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
||||||
|
// pop.isClickBgDismiss = YES; // 点击背景关闭
|
||||||
__weak typeof(pop) weakPop = pop;
|
// pop.cornerRadius = 0; // 自定义 view 自处理圆角
|
||||||
view.appleLoginHandler = ^{
|
//
|
||||||
[weakPop dismiss];
|
// __weak typeof(pop) weakPop = pop;
|
||||||
// 交给 VM 统一处理 Apple 登录 + 服务端登录
|
// view.appleLoginHandler = ^{
|
||||||
[[KBLoginVM shared] signInWithAppleFromViewController:KB_CURRENT_NAV completion:^(BOOL success, NSError * _Nullable error) {
|
// [weakPop dismiss];
|
||||||
if (success) {
|
// // 交给 VM 统一处理 Apple 登录 + 服务端登录
|
||||||
[KBHUD showInfo:KBLocalized(@"Signed in successfully")];
|
// [[KBLoginVM shared] signInWithAppleFromViewController:KB_CURRENT_NAV completion:^(BOOL success, NSError * _Nullable error) {
|
||||||
} else {
|
// if (success) {
|
||||||
NSString *msg = error.localizedDescription ?: KBLocalized(@"Sign-in failed");
|
// [KBHUD showInfo:KBLocalized(@"Signed in successfully")];
|
||||||
[KBHUD showInfo:msg];
|
// } else {
|
||||||
}
|
// NSString *msg = error.localizedDescription ?: KBLocalized(@"Sign-in failed");
|
||||||
}];
|
// [KBHUD showInfo:msg];
|
||||||
};
|
// }
|
||||||
view.closeHandler = ^{ [weakPop dismiss]; };
|
// }];
|
||||||
|
// };
|
||||||
[pop pop];
|
// view.closeHandler = ^{ [weakPop dismiss]; };
|
||||||
});
|
//
|
||||||
|
// [pop pop];
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,6 +164,11 @@
|
|||||||
#pragma mark - Actions
|
#pragma mark - Actions
|
||||||
- (void)onTapBuyAction {
|
- (void)onTapBuyAction {
|
||||||
// if (self.onTapBuy) { self.onTapBuy(); }
|
// if (self.onTapBuy) { self.onTapBuy(); }
|
||||||
|
// 未登录时先跳到登录页;登录后才允许进入会员购买页
|
||||||
|
if (![KBUserSessionManager shared].isLoggedIn) {
|
||||||
|
[[KBUserSessionManager shared] goLoginVC];
|
||||||
|
return;
|
||||||
|
}
|
||||||
KBVipPay *vc = [[KBVipPay alloc] init];
|
KBVipPay *vc = [[KBVipPay alloc] init];
|
||||||
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
// 背景
|
// 背景
|
||||||
@property (nonatomic, strong) UIImageView *bgImageView; // 整体背景图:login_bg_icon
|
@property (nonatomic, strong) UIImageView *bgImageView; // 整体背景图:login_bg_icon
|
||||||
@property (nonatomic, strong) UIImageView *topRightImageView; // 顶部右侧装饰图:login_jianp_icon
|
@property (nonatomic, strong) UIImageView *topRightImageView; // 顶部右侧装饰图:login_jianp_icon
|
||||||
|
@property (nonatomic, strong) UIButton *backButton; // 顶部左侧返回按钮
|
||||||
|
|
||||||
// 底部白色容器(仅上圆角 26)
|
// 底部白色容器(仅上圆角 26)
|
||||||
@property (nonatomic, strong) UIView *contentContainerView;
|
@property (nonatomic, strong) UIView *contentContainerView;
|
||||||
@@ -74,6 +75,14 @@
|
|||||||
[self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.edges.equalTo(self.view);
|
make.edges.equalTo(self.view);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
// 顶部左侧返回按钮
|
||||||
|
[self.view addSubview:self.backButton];
|
||||||
|
[self.backButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.equalTo(self.view).offset(16);
|
||||||
|
make.top.equalTo(self.view).offset(KB_StatusBarHeight() + 8);
|
||||||
|
make.width.height.mas_equalTo(32);
|
||||||
|
}];
|
||||||
|
|
||||||
// 顶部右侧装饰图
|
// 顶部右侧装饰图
|
||||||
[self.view addSubview:self.topRightImageView];
|
[self.view addSubview:self.topRightImageView];
|
||||||
@@ -165,7 +174,7 @@
|
|||||||
id<UIApplicationDelegate> appDelegate = UIApplication.sharedApplication.delegate;
|
id<UIApplicationDelegate> appDelegate = UIApplication.sharedApplication.delegate;
|
||||||
if ([appDelegate respondsToSelector:@selector(setupRootVC)]) {
|
if ([appDelegate respondsToSelector:@selector(setupRootVC)]) {
|
||||||
AppDelegate *delegate = (AppDelegate *)appDelegate;
|
AppDelegate *delegate = (AppDelegate *)appDelegate;
|
||||||
[delegate setupRootVC];
|
[delegate toMainTabbarVC];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -195,6 +204,15 @@
|
|||||||
KBLOG(@"onTapForgotPassword");
|
KBLOG(@"onTapForgotPassword");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)onTapBack {
|
||||||
|
// 与 BaseViewController 的返回逻辑保持一致:优先 pop,其次 dismiss
|
||||||
|
if (self.navigationController && self.navigationController.viewControllers.count > 1) {
|
||||||
|
[self.navigationController popViewControllerAnimated:YES];
|
||||||
|
} else if (self.presentingViewController) {
|
||||||
|
[self dismissViewControllerAnimated:YES completion:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Lazy UI
|
#pragma mark - Lazy UI
|
||||||
|
|
||||||
- (UIImageView *)bgImageView {
|
- (UIImageView *)bgImageView {
|
||||||
@@ -223,6 +241,21 @@
|
|||||||
return _contentContainerView;
|
return _contentContainerView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UIButton *)backButton {
|
||||||
|
if (!_backButton) {
|
||||||
|
_backButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
UIImage *img = [UIImage imageNamed:@"back"];
|
||||||
|
if (!img) { img = [UIImage imageNamed:@"back_black_icon"]; }
|
||||||
|
if (img) {
|
||||||
|
[_backButton setImage:img forState:UIControlStateNormal];
|
||||||
|
}
|
||||||
|
_backButton.adjustsImageWhenHighlighted = YES;
|
||||||
|
_backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||||
|
[_backButton addTarget:self action:@selector(onTapBack) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _backButton;
|
||||||
|
}
|
||||||
|
|
||||||
- (UILabel *)titleLabel {
|
- (UILabel *)titleLabel {
|
||||||
if (!_titleLabel) {
|
if (!_titleLabel) {
|
||||||
_titleLabel = [UILabel new];
|
_titleLabel = [UILabel new];
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
/// 退出登录:清 Keychain + 本地缓存
|
/// 退出登录:清 Keychain + 本地缓存
|
||||||
- (void)logout;
|
- (void)logout;
|
||||||
|
|
||||||
|
- (void)goLoginVC;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#import "KBUser.h"
|
#import "KBUser.h"
|
||||||
#import "KBConfig.h"
|
#import "KBConfig.h"
|
||||||
#import <MJExtension/MJExtension.h>
|
#import <MJExtension/MJExtension.h>
|
||||||
|
#import "KBLoginVC.h"
|
||||||
/// App Group 里的用户缓存 key
|
/// App Group 里的用户缓存 key
|
||||||
static NSString * const kKBSessionUserStoreKey = @"KBSession.currentUser";
|
static NSString * const kKBSessionUserStoreKey = @"KBSession.currentUser";
|
||||||
/// “本次安装是否已初始化”标记 key(用来识别卸载重装)
|
/// “本次安装是否已初始化”标记 key(用来识别卸载重装)
|
||||||
@@ -58,14 +58,17 @@ static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialize
|
|||||||
if (self.didBootstrap) return;
|
if (self.didBootstrap) return;
|
||||||
self.didBootstrap = YES;
|
self.didBootstrap = YES;
|
||||||
|
|
||||||
BOOL hasInitializedThisInstall = [self.defaults boolForKey:kKBSessionInstallFlagKey];
|
// 使用本 App 的 standardUserDefaults 记录“本次安装是否已初始化”。
|
||||||
|
// 这样在卸载重装后,这个标记会被系统清空,从而触发一次性清理旧的 Keychain token。
|
||||||
|
NSUserDefaults *installDefaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
BOOL hasInitializedThisInstall = [installDefaults boolForKey:kKBSessionInstallFlagKey];
|
||||||
|
|
||||||
KBAuthManager *auth = [KBAuthManager shared]; // 内部会 reloadFromKeychain
|
KBAuthManager *auth = [KBAuthManager shared]; // 内部会 reloadFromKeychain
|
||||||
|
|
||||||
if (!hasInitializedThisInstall) {
|
if (!hasInitializedThisInstall) {
|
||||||
// 说明是“卸载重装后的第一次运行”(或者真正第一次安装)
|
// 说明是“卸载重装后的第一次运行”(或者真正第一次安装)
|
||||||
[self.defaults setBool:YES forKey:kKBSessionInstallFlagKey];
|
[installDefaults setBool:YES forKey:kKBSessionInstallFlagKey];
|
||||||
[self.defaults synchronize];
|
[installDefaults synchronize];
|
||||||
|
|
||||||
// 若此时 Keychain 里已有 token,多半是上一次安装遗留的;按你的需求清掉
|
// 若此时 Keychain 里已有 token,多半是上一次安装遗留的;按你的需求清掉
|
||||||
if (auth.current.accessToken.length > 0) {
|
if (auth.current.accessToken.length > 0) {
|
||||||
@@ -160,4 +163,9 @@ static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialize
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)goLoginVC{
|
||||||
|
KBLoginVC *vc = [[KBLoginVC alloc] init];
|
||||||
|
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
[[KBNetworkManager shared] GET:API_LOGOUT
|
[[KBNetworkManager shared] GET:API_LOGOUT
|
||||||
parameters:nil
|
parameters:nil
|
||||||
headers:nil
|
headers:nil
|
||||||
|
autoShowBusinessError:NO
|
||||||
completion:^(NSDictionary *jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
completion:^(NSDictionary *jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||||
// 不管成功失败,都先把 HUD 收掉
|
// 不管成功失败,都先把 HUD 收掉
|
||||||
[KBHUD dismiss];
|
[KBHUD dismiss];
|
||||||
@@ -34,9 +35,9 @@
|
|||||||
// 回到登录 / 主界面
|
// 回到登录 / 主界面
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
id<UIApplicationDelegate> appDelegate = UIApplication.sharedApplication.delegate;
|
id<UIApplicationDelegate> appDelegate = UIApplication.sharedApplication.delegate;
|
||||||
if ([appDelegate respondsToSelector:@selector(setupRootVC)]) {
|
if ([appDelegate respondsToSelector:@selector(toMainTabbarVC)]) {
|
||||||
AppDelegate *delegate = (AppDelegate *)appDelegate;
|
AppDelegate *delegate = (AppDelegate *)appDelegate;
|
||||||
[delegate setupRootVC];
|
[delegate toMainTabbarVC];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ typedef NS_ERROR_ENUM(KBNetworkErrorDomain, KBNetworkError) {
|
|||||||
|
|
||||||
/// JSON 回调:约定服务端统一返回顶层 NSDictionary({code,message,data,...})
|
/// JSON 回调:约定服务端统一返回顶层 NSDictionary({code,message,data,...})
|
||||||
typedef void(^KBNetworkCompletion)(NSDictionary *_Nullable json,
|
typedef void(^KBNetworkCompletion)(NSDictionary *_Nullable json,
|
||||||
NSURLResponse * _Nullable response,
|
NSURLResponse *_Nullable response,
|
||||||
NSError * _Nullable error);
|
NSError *_Nullable error);
|
||||||
|
|
||||||
/// 二进制回调:用于下载 zip、图片等原始数据
|
/// 二进制回调:用于下载 zip、图片等原始数据
|
||||||
typedef void(^KBNetworkDataCompletion)(NSData *_Nullable data,
|
typedef void(^KBNetworkDataCompletion)(NSData *_Nullable data,
|
||||||
@@ -48,6 +48,13 @@ typedef void(^KBNetworkDataCompletion)(NSData *_Nullable data,
|
|||||||
@property (nonatomic, assign) NSTimeInterval timeout;
|
@property (nonatomic, assign) NSTimeInterval timeout;
|
||||||
|
|
||||||
/// GET 请求,parameters 会拼到 URL 上
|
/// GET 请求,parameters 会拼到 URL 上
|
||||||
|
- (nullable NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
|
parameters:(nullable NSDictionary *)parameters
|
||||||
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
|
autoShowBusinessError:(BOOL)autoShowBusinessError
|
||||||
|
completion:(KBNetworkCompletion)completion;
|
||||||
|
|
||||||
|
/// 兼容旧调用:默认 autoShowBusinessError = YES
|
||||||
- (nullable NSURLSessionDataTask *)GET:(NSString *)path
|
- (nullable NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
parameters:(nullable NSDictionary *)parameters
|
parameters:(nullable NSDictionary *)parameters
|
||||||
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
@@ -60,6 +67,13 @@ typedef void(^KBNetworkDataCompletion)(NSData *_Nullable data,
|
|||||||
completion:(KBNetworkDataCompletion)completion;
|
completion:(KBNetworkDataCompletion)completion;
|
||||||
|
|
||||||
/// POST JSON 请求,jsonBody 会以 application/json 发送
|
/// POST JSON 请求,jsonBody 会以 application/json 发送
|
||||||
|
- (nullable NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
|
jsonBody:(nullable id)jsonBody
|
||||||
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
|
autoShowBusinessError:(BOOL)autoShowBusinessError
|
||||||
|
completion:(KBNetworkCompletion)completion;
|
||||||
|
|
||||||
|
/// 兼容旧调用:默认 autoShowBusinessError = YES
|
||||||
- (nullable NSURLSessionDataTask *)POST:(NSString *)path
|
- (nullable NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
jsonBody:(nullable id)jsonBody
|
jsonBody:(nullable id)jsonBody
|
||||||
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
|
|||||||
@@ -53,12 +53,15 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
#pragma mark - Public
|
#pragma mark - Public
|
||||||
|
|
||||||
|
// JSON GET:可控制业务错误是否由内部弹出
|
||||||
- (NSURLSessionDataTask *)GET:(NSString *)path
|
- (NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
parameters:(NSDictionary *)parameters
|
parameters:(NSDictionary *)parameters
|
||||||
headers:(NSDictionary<NSString *,NSString *> *)headers
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
completion:(KBNetworkCompletion)completion {
|
autoShowBusinessError:(BOOL)autoShowBusinessError
|
||||||
|
completion:(KBNetworkCompletion)completion {
|
||||||
NSLog(@"[KBNetworkManager] GET called, enabled=%d, path=%@", self.isEnabled, path);
|
NSLog(@"[KBNetworkManager] GET called, enabled=%d, path=%@", self.isEnabled, path);
|
||||||
if (![self ensureEnabled:completion]) return nil;
|
if (![self ensureEnabled:completion]) return nil;
|
||||||
NSString *urlString = [self buildURLStringWithPath:path];
|
NSString *urlString = [self buildURLStringWithPath:path];
|
||||||
@@ -84,14 +87,30 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
req.allHTTPHeaderFields ?: @{},
|
req.allHTTPHeaderFields ?: @{},
|
||||||
paramStr);
|
paramStr);
|
||||||
#endif
|
#endif
|
||||||
return [self startJSONTaskWithRequest:req completion:completion];
|
return [self startJSONTaskWithRequest:req
|
||||||
|
autoShowBusinessError:autoShowBusinessError
|
||||||
|
completion:completion];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认 GET:自动弹业务错误
|
||||||
|
- (NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
return [self GET:path
|
||||||
|
parameters:parameters
|
||||||
|
headers:headers
|
||||||
|
autoShowBusinessError:YES
|
||||||
|
completion:completion];
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON POST:可控制业务错误是否由内部弹出
|
||||||
- (NSURLSessionDataTask *)POST:(NSString *)path
|
- (NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
jsonBody:(id)jsonBody
|
jsonBody:(id)jsonBody
|
||||||
headers:(NSDictionary<NSString *,NSString *> *)headers
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
completion:(KBNetworkCompletion)completion {
|
autoShowBusinessError:(BOOL)autoShowBusinessError
|
||||||
NSLog(@"=====");
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
NSLog(@"[KBNetworkManager] POST called, enabled=%d, path=%@", self.isEnabled, path);
|
||||||
if (![self ensureEnabled:completion]) return nil;
|
if (![self ensureEnabled:completion]) return nil;
|
||||||
NSString *urlString = [self buildURLStringWithPath:path];
|
NSString *urlString = [self buildURLStringWithPath:path];
|
||||||
if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; }
|
if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; }
|
||||||
@@ -113,7 +132,21 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
req.allHTTPHeaderFields ?: @{},
|
req.allHTTPHeaderFields ?: @{},
|
||||||
bodyStr);
|
bodyStr);
|
||||||
#endif
|
#endif
|
||||||
return [self startJSONTaskWithRequest:req completion:completion];
|
return [self startJSONTaskWithRequest:req
|
||||||
|
autoShowBusinessError:autoShowBusinessError
|
||||||
|
completion:completion];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认 POST:自动弹业务错误
|
||||||
|
- (NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
|
jsonBody:(id)jsonBody
|
||||||
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
return [self POST:path
|
||||||
|
jsonBody:jsonBody
|
||||||
|
headers:headers
|
||||||
|
autoShowBusinessError:YES
|
||||||
|
completion:completion];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 原始二进制 GET,用于下载 zip、图片等
|
// 原始二进制 GET,用于下载 zip、图片等
|
||||||
@@ -190,6 +223,7 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURLSessionDataTask *)startJSONTaskWithRequest:(NSURLRequest *)req
|
- (NSURLSessionDataTask *)startJSONTaskWithRequest:(NSURLRequest *)req
|
||||||
|
autoShowBusinessError:(BOOL)autoShowBusinessError
|
||||||
completion:(KBNetworkCompletion)completion {
|
completion:(KBNetworkCompletion)completion {
|
||||||
NSLog(@"[KBNetworkManager] startAFTaskWithRequest: %@", req.URL.absoluteString);
|
NSLog(@"[KBNetworkManager] startAFTaskWithRequest: %@", req.URL.absoluteString);
|
||||||
// 响应先用原始数据返回,再按 Content-Type 解析 JSON(与原实现一致)
|
// 响应先用原始数据返回,再按 Content-Type 解析 JSON(与原实现一致)
|
||||||
@@ -266,18 +300,23 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
// 统一解析业务 code:约定后端顶层包含 { code, message, data }
|
// 统一解析业务 code:约定后端顶层包含 { code, message, data }
|
||||||
NSInteger bizCode = KBBizCodeFromJSONObject(dict);
|
NSInteger bizCode = KBBizCodeFromJSONObject(dict);
|
||||||
if (bizCode != NSNotFound && bizCode != KBBizCodeSuccess) {
|
if (bizCode != NSNotFound && bizCode != KBBizCodeSuccess) {
|
||||||
// 非成功业务 code:执行通用处理(如 token 失效)并通过 error 方式回调
|
// 非成功业务 code:执行通用处理(如 token 失效)并通过 error 方式回调
|
||||||
[self kb_handleBizCode:bizCode json:dict response:response];
|
BOOL handledByAuth = [self kb_handleBizCode:bizCode json:dict response:response];
|
||||||
NSString *msg = KBBizMessageFromJSONObject(json) ?: KBLocalized(@"Server error");
|
NSString *msg = KBBizMessageFromJSONObject(dict) ?: KBLocalized(@"Server error");
|
||||||
NSError *bizErr = [NSError errorWithDomain:KBNetworkErrorDomain
|
if (autoShowBusinessError && !handledByAuth) {
|
||||||
code:KBNetworkErrorBusiness
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
userInfo:@{
|
[KBHUD showInfo:msg];
|
||||||
NSLocalizedDescriptionKey : msg,
|
});
|
||||||
@"code" : @(bizCode)
|
|
||||||
}];
|
|
||||||
if (completion) completion(dict, response, bizErr);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
NSError *bizErr = [NSError errorWithDomain:KBNetworkErrorDomain
|
||||||
|
code:KBNetworkErrorBusiness
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey : msg,
|
||||||
|
@"code" : @(bizCode)
|
||||||
|
}];
|
||||||
|
if (completion) completion(dict, response, bizErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// code 缺失或为成功,按正常成功回调
|
// code 缺失或为成功,按正常成功回调
|
||||||
if (completion) completion(dict, response, nil);
|
if (completion) completion(dict, response, nil);
|
||||||
} else {
|
} else {
|
||||||
@@ -328,8 +367,9 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
|
|
||||||
#pragma mark - Private helpers
|
#pragma mark - Private helpers
|
||||||
|
|
||||||
/// 处理通用业务 code(token 失效、被踢下线等)
|
/// 处理通用业务 code(token 失效、被踢下线等);
|
||||||
- (void)kb_handleBizCode:(NSInteger)bizCode
|
/// 返回 YES 表示该 code 已在此处消费(例如已清理登录态并提示),外部无需再提示。
|
||||||
|
- (BOOL)kb_handleBizCode:(NSInteger)bizCode
|
||||||
json:(id)json
|
json:(id)json
|
||||||
response:(NSURLResponse *)response {
|
response:(NSURLResponse *)response {
|
||||||
switch (bizCode) {
|
switch (bizCode) {
|
||||||
@@ -361,10 +401,12 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
|||||||
object:nil
|
object:nil
|
||||||
userInfo:info];
|
userInfo:info];
|
||||||
});
|
});
|
||||||
|
return YES;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion {
|
- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion {
|
||||||
|
|||||||
Reference in New Issue
Block a user