diff --git a/keyBoard/Class/Common/V/KBHUD.m b/keyBoard/Class/Common/V/KBHUD.m index 20fe2c0..326d7d9 100644 --- a/keyBoard/Class/Common/V/KBHUD.m +++ b/keyBoard/Class/Common/V/KBHUD.m @@ -17,6 +17,7 @@ static __weak MBProgressHUD *sHUD = nil; static KBHUDMaskType sMaskType = KBHUDMaskTypeClear; // 全局默认遮罩 static BOOL sDefaultTapToDismiss = NO; // 全局默认:不允许点击关闭 static NSTimeInterval sAutoDismiss = 1.2; +static NSTimeInterval sLoadingMaxDuration = 20.0; // loading 最长展示时长,避免异常分支一直转圈 static __weak UIView *sContainerView = nil; // 缺省承载视图(扩展里必须设置) #pragma mark - Private Helpers @@ -129,8 +130,27 @@ static __weak UIView *sContainerView = nil; // 缺省承载视图( [self dismiss]; } ++ (void)_kb_loadingTimeoutDismiss { + [self dismiss]; +} + ++ (void)cancelLoadingAutoDismiss { + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(_kb_loadingTimeoutDismiss) + object:nil]; +} + ++ (void)scheduleLoadingAutoDismiss { + [self cancelLoadingAutoDismiss]; + if (sLoadingMaxDuration <= 0) { return; } + [self performSelector:@selector(_kb_loadingTimeoutDismiss) + withObject:nil + afterDelay:sLoadingMaxDuration]; +} + + (void)_showText:(NSString *)text icon:(nullable UIImage *)icon { [self onMain:^{ + [self cancelLoadingAutoDismiss]; MBProgressHUD *loadingHUD = sHUD; if (loadingHUD) { [loadingHUD hideAnimated:YES]; @@ -177,6 +197,7 @@ static __weak UIView *sContainerView = nil; // 缺省承载视图( if (!hud) { return; } hud.mode = MBProgressHUDModeIndeterminate; hud.label.text = status ?: @""; + [self scheduleLoadingAutoDismiss]; }]; } @@ -191,6 +212,7 @@ static __weak UIView *sContainerView = nil; // 缺省承载视图( hud.mode = MBProgressHUDModeDeterminate; hud.progress = progress; hud.label.text = status ?: @""; + [self scheduleLoadingAutoDismiss]; }]; } @@ -205,9 +227,9 @@ static __weak UIView *sContainerView = nil; // 缺省承载视图( + (void)showError:(NSString *)status { [self _showText:status ?: KBLocalized(@"Failed") icon:nil]; } -+ (void)dismiss { [self onMain:^{ [sHUD hideAnimated:YES]; }]; } ++ (void)dismiss { [self onMain:^{ [self cancelLoadingAutoDismiss]; [sHUD hideAnimated:YES]; }]; } -+ (void)dismissWithDelay:(NSTimeInterval)delay { [self onMain:^{ [sHUD hideAnimated:YES afterDelay:delay]; }]; } ++ (void)dismissWithDelay:(NSTimeInterval)delay { [self onMain:^{ [self cancelLoadingAutoDismiss]; [sHUD hideAnimated:YES afterDelay:delay]; }]; } #pragma mark - Config diff --git a/keyBoard/Class/Network/KBNetworkManager.m b/keyBoard/Class/Network/KBNetworkManager.m index aef2a07..1f55502 100644 --- a/keyBoard/Class/Network/KBNetworkManager.m +++ b/keyBoard/Class/Network/KBNetworkManager.m @@ -387,6 +387,10 @@ autoShowBusinessError:YES self.manager.responseSerializer = [AFHTTPResponseSerializer serializer]; NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:req uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { NSLog(@"[KBNetworkManager] task finished, error = %@", error); + // 无论成功/失败,网络回包后统一兜底关闭 loading HUD,避免异常分支遗漏导致一直转圈。 + dispatch_async(dispatch_get_main_queue(), ^{ + [KBHUD dismiss]; + }); // AFN 默认对非 2xx 的状态码返回 error;这里先日志,再直接回调上层 if (error) { #if DEBUG @@ -494,6 +498,9 @@ autoShowBusinessError:YES self.manager.responseSerializer = [AFHTTPResponseSerializer serializer]; NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:req uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { NSLog(@"[KBNetworkManager] data task finished, error = %@", error); + dispatch_async(dispatch_get_main_queue(), ^{ + [KBHUD dismiss]; + }); if (error) { if (completion) completion(nil, response, error); return;