昨天遇到了一个问题,大概意思就是:
屏幕快照 2019-02-23 上午8.26.09.png自己当然知道要使用多线程实现,等所有的耗时操作完成再更新UI,咨询了朋友们,有说用GCD的,有说用信号量的,有说用栅栏函数的,有说2和3都基于1基础上执行。。。。。。
今天早上一醒就打开电脑试验了一下。
考虑到在没有顺序要求的情况下,使用GCD Group进行线程调度是最合适的,如果存在顺序要求,需要使用信号量了。
代码如下:
// 移除dishViewModel
func removeAndResetDishes(_ dishViewModels: [DishViewModel], shouldRemoveDelay: Bool, completed:(()->())?) {
var needRemoveDishViewModels: [DishViewModel]!
if shouldRemoveDelay {
needRemoveDishViewModels = dishViewModels
// 操作1
var needUpdateDelayLabels = [DishLabel]()
for dishViewModel in dishViewModels {
for label in dishViewModel.labels {
if label.statuses.contains(.delay) {
label.cancleDelayTime = label.delayTime
label.cancleDelayBrforeCount = label.count
label.setup(delayTime: "0")
label.count = 1
needUpdateDelayLabels.append(label)
}
}
}
// 操作2 (可能进行耗时操作网络请求)
HUDManager.showIndicatorMessage()
//任务队列
let queue = DispatchQueue(label: "requestHandler")
//分组
let group = DispatchGroup()
var removeDelayRequest: Bool = false
queue.async(group: group) {
let sema = DispatchSemaphore(value: 0)
DelayDishService.shared.delay(dishViewLabels: needUpdateDelayLabels, callback: { (result) in
switch result {
case .success(_):
print("成功")
removeDelayRequest = true
sema.signal()
case .failure(let error):
//print("失败, \(error.localizedDescription)")
HUDManager.showAutoDismissFailedMessage(error.localizedDescription)
removeDelayRequest = false
for dishViewModel in dishViewModels {
for label in dishViewModel.labels {
if label.statuses.contains(.delay) {
label.setup(delayTime: label.cancleDelayTime)
label.count = label.cancleDelayBrforeCount
needUpdateDelayLabels.append(label)
}
}
}
sema.signal()
}
})
sema.wait()
}
// 更新本地数据,刷新UI
group.notify(queue: DispatchQueue.main, execute: {[weak self] in
if removeDelayRequest {
self?.remove(needRemoveDishViewModels)
self?.resetDishViewModels(needRemoveDishViewModels)
completed?()
}
HUDManager.hide()
})
}else{
needRemoveDishViewModels = dishViewModels.filter({ (dishViewModel) -> Bool in
var flag = true
for label in dishViewModel.labels {
if label.statuses.contains(.delay) {
flag = false
break
}
}
return flag
})
let delayDishViewModels = dishViewModels.filter({ (dishViewModel) -> Bool in
var flag = true
for label in dishViewModel.labels {
if label.statuses.contains(.delay) {
flag = false
break
}
}
return !flag
})
// 延迟单独处理,保留非延时规格,清空延时规格
for dishViewModel in delayDishViewModels {
for label in dishViewModel.labels {
if !label.statuses.contains(.delay) {
label.count = 0
label.selectDelayTime = 0
}
}
}
}
}
操作2的方法实现:
public func delay(dishViewLabels:[DishLabel], callback: @escaping ResultCallback) {
let dishInfo = makeDishInfo(withDishViewLabels: dishViewLabels)
if dishInfo.isEmpty {
callback(DataResult.success(JSONDictionary()))
return
}
var params = [
"bPrint": "Y",
"batchNo": Int64(Date().timeIntervalSince1970 * 1000),
"companyId": WaiterManager.shared.companyID,
"shopId": WaiterManager.shared.shopID,
"staffId": WaiterManager.shared.waiterID,
"tableBillId": TableManager.shared.currentTableBillID,
"tableId": TableManager.shared.currentTableID,
"printType": DishPrintType.pointHalf.rawValue,
"tableNo": TableManager.shared.currentTableNo
] as JSONDictionary
params["dishInfo"] = dishInfo
print("=================延时菜品操作更改================\n",dishInfo)
HUDManager.showIndicatorMessage()
NetRequest.request(withInterface: InterfaceEnum.delayOrder, requestData: params, method: .Post) { result in
print("延时菜品:",result)
HUDManager.hide()
if result.isSuccess {
UploadDishsService.shared.upload { (result) in
switch result {
case .success(_):
print("上传菜品成功")
case .failure(let error):
print("上传菜品失败, \(error.localizedDescription)")
}
}
}
callback(result)
}
}
这里总结下注意事项:
1.信号量的使用;
2.方法执行完要刷新UI,使用回调实现方便;
3.对于方法中的数据请求操作,可能请求,可能不请求,可以在方法返回前包装一个成功的返回值回调即可;
4.对于主线程需不需要刷新UI,可以使用变量记录,成功则刷新,失败则不需要刷新。
暂时记录这么多吧,实话说以前还真没这么搞过,以前都是很傻的请求成功里面操作即可,这情况压根走不下去呀。
参考博客:
https://blog.csdn.net/wantbar/article/details/65690508
https://www.jianshu.com/p/60a66c38f5d6
https://www.jianshu.com/p/c9f373897437
网友评论