2016-12-16 5 views
0

Я создал группу Dispatch, в которой запущены три одновременные очереди, а затем уведомляет группу об обновлении, что происходит хорошо, и все это я включил в функцию с завершением handler.now проблема, с которой я сталкиваюсь, обработчик завершения вызова вызывается до завершения выполнения очереди. Как я могу решить эту проблему, пожалуйста, совет?Обработчик завершения не работает, как ожидалось, с диспетчерской группой и параллельной очередью

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 
              { 

              } 
            }) 
           } 
+0

Вы должны поместить код внутри 'notify' закрытия. – shallowThought

+0

@shallowThought - попробовал, но это, похоже, не работает. –

ответ

0

Вы смешиваете много вещей. Вы пытаетесь получить уведомление, но также пытаетесь подождать.

completion() Ваш обработчик и код, отмеченные

// Ниже кода выполняется до завершения очереди "

называется/погонный вне вашего блока уведомления ...

AFAICS, нет причин использовать notify или wait whithin loadCompaniesFromSynch(), так как вы не называете асин c задач.

Как я понимаю, что вы хотите сделать, это сделать свой тяжелый io материал в фоновом режиме. В этом случае удалите все файлы 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 
} 

Надеюсь, что это поможет.

+0

@ mustowThought- Выше решение отлично, но мой родительский цикл имеет длину около 133500, поэтому я хочу выполнить его параллельно, чтобы уменьшить время. Лучшее решение для достижения этого? –

+0

прямо сейчас занимает более полутора часов. –

+0

К какому «родительскому циклу» вы относитесь? – shallowThought