多异步线程下更新MBProgressHUD进度条及QoS警告问题求助
解决MBProgressHUD进度更新及QoS优先级反转警告问题
一、先搞定进度不更新的核心问题
你这进度不更新,大概率是直接用单个任务的进度更新HUD,多个任务进度互相覆盖,再加上HUD没配置成进度模式导致的。按下面步骤调整:
把HUD改成进度显示模式
初始化HUD时必须指定进度模式,默认模式是加载转圈,不会显示进度条:self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; self.hud.mode = MBProgressHUDModeDeterminate; // 条形进度条,想用环形就换MBProgressHUDModeAnnularDeterminate self.hud.label.text = @"上传中..."; self.hud.detailsLabel.text = @"0%";注意给HUD加个控制器的强引用属性,别用局部变量导致提前释放。
计算总上传进度,别单独用单个任务进度
4个任务各占总进度的25%,得把每个任务的进度按权重累加。在控制器里加两个变量:@property (nonatomic, assign) CGFloat totalUploadProgress; @property (nonatomic, assign) NSInteger finishedTaskCount;然后在每个上传任务的progress回调里更新总进度:
__weak typeof(self) weakSelf = self; [uploadManager uploadImage:image progress:^(CGFloat percent) { // 单个任务进度占总进度的25%,计算当前任务的贡献值 CGFloat currentTaskContribution = percent * 0.25; // 减去之前该任务的贡献值,避免重复累加 CGFloat previousTaskProgress = weakSelf.totalUploadProgress - (weakSelf.finishedTaskCount * 0.25); weakSelf.totalUploadProgress = weakSelf.totalUploadProgress - previousTaskProgress + currentTaskContribution; // 切主队列更新UI dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.hud.progress = weakSelf.totalUploadProgress; weakSelf.hud.detailsLabel.text = [NSString stringWithFormat:@"%.0f%%", weakSelf.totalUploadProgress * 100]; }); } completion:^(BOOL success) { weakSelf.finishedTaskCount++; if (weakSelf.finishedTaskCount == 4) { [MBProgressHUD hideHUDForView:weakSelf.view animated:YES]; // 上传完成后的逻辑 } }];
二、解决QoS优先级反转警告
那个紫色警告是因为上传回调的线程没指定QoS等级,而你发起上传的队列是QOS_CLASS_USER_INITIATED级别,导致优先级反转。按下面两种方式处理:
给上传回调队列指定对应QoS
如果你的上传方法支持传入回调队列,直接指定和发起队列相同的QoS:// 创建带USER_INITIATED优先级的回调队列 dispatch_queue_t uploadCallbackQueue = dispatch_queue_create("com.yourapp.upload.callback", DISPATCH_QUEUE_CONCURRENT); dispatch_set_target_queue(uploadCallbackQueue, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)); // 传入自定义队列作为回调队列 [uploadManager uploadImage:image callbackQueue:uploadCallbackQueue progress:^(CGFloat percent) { // 这里回调线程已经是USER_INITIATED级别,再切主队列就不会触发警告 dispatch_async(dispatch_get_main_queue(), ^{ // 更新HUD逻辑 }); } completion:nil];别用dispatch_group_wait阻塞高优先级队列
如果你之前用了dispatch_group_wait在主线程或USER_INITIATED队列里,这会直接导致警告——因为wait会阻塞高优先级队列,等待低优先级的上传任务完成。改成用dispatch_group_notify处理完成事件:dispatch_group_t uploadGroup = dispatch_group_create(); // 每个上传任务加入group dispatch_group_enter(uploadGroup); [uploadManager uploadImage:image progress:^(CGFloat percent) { // 更新进度 } completion:^(BOOL success) { dispatch_group_leave(uploadGroup); }]; // 用notify监听完成,而非wait阻塞 dispatch_group_notify(uploadGroup, dispatch_get_main_queue(), ^{ [MBProgressHUD hideHUDForView:self.view animated:YES]; // 上传完成逻辑 });
三、额外检查点
- 先加NSLog确认上传任务的progress回调是否真的触发,percent值有没有变化;
- 别在progress回调里做耗时操作,只保留UI更新的最小逻辑;
- 确保所有上传任务的completion回调都正确调用了
dispatch_group_leave,避免group一直等待。
内容的提问来源于stack exchange,提问作者Christopher Sonny
相关产品推荐
相关产品推荐

