菜鸟教程小白 发表于 2022-12-12 23:14:33

ios - 完成处理程序未按预期与调度组和并发队列一起工作


                                            <p><p>我创建了一个调度组,其中三个并发队列正在运行,然后通知组进行更新,这一切都很好,我已经将所有这些都放入了一个带有完成处理程序的函数中。现在我面临的问题是完成处理程序在队列执行完成之前被调用。我该如何解决这个问题,请指教?</p>

<pre><code>   func loadCompaniesFromSynch(_ data: Data, completionHandler: @escaping(String) -&gt; ())
{

    var companyFile = &#34;&#34;
    companies = ()
    let batchGroup = DispatchGroup()
    let queue = DispatchQueue(label: &#34;Batch Queue&#34;, 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? [] as NSArray!

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

    var company: Company?

    if newCompanyObj?.count &gt; 0 {

      if let companies = oldCompanies
      {
            for com incompanies as! []
            {

                company = Company()
                company!.orgCode = com[&#34;ORG_CODE&#34;] as? String
                company!.orgDescription = com[&#34;ORG_DESCRIPTION&#34;] as? String

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

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



      }

    print(&#34;loadCompaniesFromSynch &gt;&gt;oldCompanies &gt;&gt;\(oldCompanies.count) Comapnies Count\(self.companies!.count)&#34;)

      var dataDict = Dictionary&lt;String,String&gt;()

      if let json =newCompanyObjas NSDictionary!
      {
            if let companies = json[&#34;RESULTS&#34;] as? NSDictionary
            {
                if let companiesNew = companies[&#34;COMPANIES&#34;] as? []
                {
                   // for com in companiesNew

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

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



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


                  batchGroup.enter()
                  queue.async(group: batchGroup)
                  {
                        if (addArray.count &gt; 0 )
                        {
                            addCompanies = ()
                            for (index,item) in addArray.enumerated()
                            {

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

                        }
                        batchGroup.leave()

                  }

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

                        if updateArray.count &gt; 0
                        {
                            updateCompanies = ()


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

                        }
                        }
                        batchGroup.leave()
                  }

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

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

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

                        }

                        batchGroup.leave()
                  }


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

                        if updateCompanies?.count == updateArray.count{

                            //self.companies = Array(comapnySet)
                            print(&#34;count before \(self.companies?.count)&#34;)

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

                        //self.companies =Array(comapnySet.intersection(Set(updateCompanies!)))
                            print(&#34;after delete \(self.companies?.count)&#34;)

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


                            print(&#34;update array count \(updateArray.count) ----- and update Companies count --\(self.companies?.count)&#34;)
                            updateCompanies = nil

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

                            addCompanies = nil
                        }

                  }

                  batchGroup.wait()
               }
            }

//**Below code is executed before queue completion**
            if let status = json[&#34;STATUS&#34;] as? String
            {
                dataDict      = status
            }
            if let message = json[&#34;MESSAGE&#34;] as? String
            {
                dataDict = message
            }
      }

      var newCompanyArray:Array&lt;AnyObject&gt; = []
      var dict = Dictionary&lt;String,String&gt;()


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

            newCompanyArray.append(dict as AnyObject)
      }

      let isValidJson = JSONSerialization.isValidJSONObject(newCompanyArray)


      if newCompanyArray.count &gt; 0 &amp;&amp; isValidJson
      {
            let companyCount = newCompanyArray.count - oldCompanies.count

            let replaceComCount = self.utility!.replace(self.constants!.logs.LOG_COMPANY_SYNC_END,originalString: &#34;&lt;COUNT&gt;&#34;,withString: &#34;\(companyCount)&#34;)


            self.parser!.setLogValueToXml(replaceComCount, logType:
                self.constants!.logs.LOG_TYPE_ACTIVITY, fileLogType: &#34;&#34;)


            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 = &#34;Companies_\(self.dateUtil.getCurrentDateTime())&#34; //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
                                          {

                                          }
                                    })
                              }
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>你混淆了很多东西。您正在尝试获得通知,但您也在尝试等待。</p>

<p>您的 <code>completion()</code>处理程序和标有 </p> 的代码

<blockquote>
<p>//<strong>Below code is executed before queue completion</strong>&#34;</p>
</blockquote>

<p>在您的通知 block 之外被调用/运行...</p>

<p>AFAICS,没有理由在 <code>loadCompaniesFromSynch()</code> 中使用 <code>notify</code> 或 <code>wait</code>,因为您不调用任何异步任务它。</p>

<p>我怎么理解,你想做的是在后台做你繁重的 io 工作。在这种情况下,删除所有 <code>DispatchGroup</code> 东西并调度空洞函数。无需等待/通知,因为您正在使用完成处理程序。检查以下内容以获得想法:</p>

<pre><code>    func loadCompaniesFromSynch(_ data: Data, completionHandler: @escaping(String) -&gt; ()) {
    // 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
}
</code></pre>

<p>希望这会有所帮助。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 完成处理程序未按预期与调度组和并发队列一起工作,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/41184178/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/41184178/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 完成处理程序未按预期与调度组和并发队列一起工作