美文网首页
Swift信号量实现多个操作顺序执行

Swift信号量实现多个操作顺序执行

作者: 玉思盈蝶 | 来源:发表于2019-02-23 08:41 被阅读5次

    昨天遇到了一个问题,大概意思就是:

    屏幕快照 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

    大家周末快乐哈!!!

    相关文章

      网友评论

          本文标题:Swift信号量实现多个操作顺序执行

          本文链接:https://www.haomeiwen.com/subject/udeuyqtx.html