完成处理程序与Dispatch Group和Concurrent Queue无法正常工作

时间:2016-12-16 12:13:45

标签: ios swift swift3 grand-central-dispatch

我已经创建了一个Dispatch组,其中有三个并发队列正在运行,然后通知组进行更新,这很好,所有这些我已经放入了一个带有完成处理程序的函数。现在问题我&# 39; m面向完成处理程序在队列执行完成之前调用。我可以解决这个问题,请指教吗?

   func loadCompaniesFromSynch(_ data: Data, completionHandler: @escaping(String) -> ())
{

    var companyFile = ""
    companies = [Company]()
    let batchGroup = DispatchGroup()
    let queue = DispatchQueue(label: "Batch Queue", qos: .background, attributes: .concurrent)

    if !FileManager.default.fileExists(atPath: self.fileMgr.getDocumentPath()) {
        self.fileMgr.createFileDirectory(self.constants!.APP_FOLDER)
    }

    companyFile =    self.fileMgr.getDocumentFilePath(self.fileMgr.getCacheData(constants!.COMPANIES_LAST_SYNCH_DATE) as! String)
    let dataOld: Data = try! Data(contentsOf: URL(fileURLWithPath: companyFile),options: NSData.ReadingOptions.uncached)

    let oldCompanies: NSArray! = (try? JSONSerialization.jsonObject(with: dataOld, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [[String:Any]] as NSArray!

    let newCompanyObj: NSDictionary? = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)) as? NSDictionary

    var company: Company?

    if newCompanyObj?.count > 0 {

        if let companies = oldCompanies
        {
            for com in  companies as! [[String: AnyObject]]
            {

                company = Company()
                company!.orgCode = com["ORG_CODE"] as? String
                company!.orgDescription = com["ORG_DESCRIPTION"] as? String

                if let btlOrg = com["OBX_BTL_CODE"] as? String
                {
                    company!.orgBtlCode = btlOrg
                    company!.orgBtlDescription = com["BTL_DESCRIPTION"] as? String
                }
                company!.orgStatus = com["ORG_STATUS"] as! String?

                self.companies!.append(company!)
                company = nil
            }



        }

    print("loadCompaniesFromSynch >>  oldCompanies >>\(oldCompanies.count) Comapnies Count  \(self.companies!.count)")

        var dataDict = Dictionary<String,String>()

        if let json =  newCompanyObj  as NSDictionary!
        {
            if let companies = json["RESULTS"] as? NSDictionary
            {
                if let companiesNew = companies["COMPANIES"] as? [[String: AnyObject]]
                {
                   // for com in companiesNew 

                    let addArray = companiesNew.filter { $0["ORG_STATUS"] as! String == ComapnyStatus.ADD.rawValue}
                    let deleteArray = companiesNew.filter { $0["ORG_STATUS"] as! String == ComapnyStatus.DELETED.rawValue}
                    let updateArray = companiesNew.filter { $0["ORG_STATUS"] as! String == ComapnyStatus.UPDATE.rawValue}

                    print(addArray.count)
                    print(deleteArray.count)
                    print(updateArray.count)



                    var addCompanies: [Company]?
                    var updateCompanies:[Company]?
                     var comapnySet = Set(self.companies!)


                    batchGroup.enter()
                    queue.async(group: batchGroup)
                    {
                        if (addArray.count > 0 )
                        {
                            addCompanies = [Company]()
                            for (index,item) in addArray.enumerated()
                            {

                                let company =       self.returnComapnyOjectfromDictionary(item as NSDictionary)
                                addCompanies!.append(company)
                                print("add loop----\(index)")
                            }

                        }
                        batchGroup.leave()

                    }

                    batchGroup.enter()
                    queue.async(group: batchGroup) {

                        if updateArray.count > 0
                        {
                            updateCompanies = [Company]()


                        for (index,item) in updateArray.enumerated()
                        {
                            let company = self.returnComapnyOjectfromDictionary(item as NSDictionary)
                             updateCompanies!.append(company)
                                print("update loop----\(index)")

                        }
                        }
                        batchGroup.leave()
                    }

                   batchGroup.enter()
                    queue.async(group: batchGroup) {

                        for (_,item) in deleteArray.enumerated()
                        {

                             let company = self.returnComapnyOjectfromDictionary(item as NSDictionary)
                            _ = self.removeObject(&self.companies!,object: company)
                            print("looop2")

                        }

                        batchGroup.leave()
                    }


                    batchGroup.notify(queue: .global(qos: .background))
                    {

                        if updateCompanies?.count == updateArray.count{

                            //self.companies = Array(comapnySet)
                            print("count before \(self.companies?.count)")

                            comapnySet.subtract(Set(updateCompanies!))
                            self.companies = Array(comapnySet)

                          //  self.companies =  Array(comapnySet.intersection(Set(updateCompanies!)))
                            print("after delete \(self.companies?.count)")

                            self.companies!.append(contentsOf: updateCompanies!)


                            print("update array count \(updateArray.count) ----- and update Companies count --\(self.companies?.count)")
                            updateCompanies = nil

                        }
                        if addCompanies?.count == addArray.count
                        {
                        self.companies!.append(contentsOf: addCompanies!)
                            print("add array count \(addArray.count) ----- and add Companies count --\(addCompanies?.count)")

                            addCompanies = nil
                        }

                    }

                    batchGroup.wait()
                 }
            }

//**Below code is executed before queue completion**
            if let status = json["STATUS"] as? String
            {
                dataDict[self.constants!.defaultsKeys.RESPONSE_STATUS]      = status
            }
            if let message = json["MESSAGE"] as? String
            {
                dataDict[self.constants!.defaultsKeys.RESPONSE_MESSAGE] = message
            }
        }

        var newCompanyArray:Array<AnyObject> = []
        var dict = Dictionary<String,String>()


        for cmp in self.companies!
        {
            dict["ORG_CODE"] = cmp.orgCode
            dict["ORG_DESCRIPTION"] = cmp.orgDescription
            dict["OBX_BTL_CODE"] = cmp.orgBtlCode
            dict["BTL_DESCRIPTION"] = cmp.orgBtlDescription
            dict["ORG_STATUS"] = cmp.orgStatus

            newCompanyArray.append(dict as AnyObject)
        }

        let isValidJson = JSONSerialization.isValidJSONObject(newCompanyArray)


        if newCompanyArray.count > 0 && isValidJson
        {
            let companyCount = newCompanyArray.count - oldCompanies.count

            let replaceComCount = self.utility!.replace(self.constants!.logs.LOG_COMPANY_SYNC_END,originalString: "<COUNT>",withString: "\(companyCount)")


            self.parser!.setLogValueToXml(replaceComCount, logType:
                self.constants!.logs.LOG_TYPE_ACTIVITY, fileLogType: "")


            let dataFinal:Data =  try! JSONSerialization.data(withJSONObject: newCompanyArray, options: [])
            self.fileMgr.removeFile(self.fileMgr.getDocumentFilePath(self.fileMgr.getCacheData(self.constants!.COMPANIES_LAST_SYNCH_DATE) as! String))
            let compniesFileName = "Companies_\(self.dateUtil.getCurrentDateTime())" //logic is to be use in synch
            self.fileMgr.setCacheData(compniesFileName as AnyObject, key: self.constants!.COMPANIES_LAST_SYNCH_DATE)

            self.fileMgr.writeFile(NSString(data: dataFinal, encoding: String.Encoding.utf8.rawValue)!,fileName :self.fileMgr.getCacheData(self.constants!.COMPANIES_LAST_SYNCH_DATE) as! String,documentDir:self.fileMgr.getDocumentPath())

        }

    }

    completionHandler(companyFile)
 }
 DispatchQueue.global(qos: .background).async
                                {
                                    self.loadCompaniesFromSynch(jNsData, completionHandler:
                                    {
                                        companyFile in

                                            if !companyFile.isEmpty
                                            {
                                            self.doPropertySync()
                                            }
                                            else
                                            {

                                            }
                                    })
                                }

1 个答案:

答案 0 :(得分:1)

你混淆了很多东西。您正试图收到通知,但您也在尝试等待。

您的completion()处理程序和标有

的代码
  

// 下面的代码在队列完成之前执行

在通知栏之外被调用/运行...

AFAICS,没有理由在notify中使用waitloadCompaniesFromSynch(),因为您不会在其中调用任何异步任务。

我的理解,你想做的是在后台做你喜欢的东西。在这种情况下,删除所有DispatchGroup内容并调度孔函数。无需等待/通知,因为您正在使用完成处理程序。检查以下内容以获得想法:

    func loadCompaniesFromSynch(_ data: Data, completionHandler: @escaping(String) -> ()) {
    // dispatch the whole thing to the global background queue
    DispatchQueue.global(qos: .background).async {

        // your original code with all DispatchGroup stuff deleted

        // call completion handler on main queue, so the caller does not have to care
        DispatchQueue.main.async {
            completionHandler(companyFile)
        }        
    } 
}

self.loadCompaniesFromSynch(jNsData) {
    companyFile in

    // do stuff after loadCompaniesFromSynch finished
}

希望这有帮助。