ios - 完成处理程序未按预期与调度组和并发队列一起工作
<p><p>我创建了一个调度组,其中三个并发队列正在运行,然后通知组进行更新,这一切都很好,我已经将所有这些都放入了一个带有完成处理程序的函数中。现在我面临的问题是完成处理程序在队列执行完成之前被调用。我该如何解决这个问题,请指教?</p>
<pre><code> func loadCompaniesFromSynch(_ data: Data, completionHandler: @escaping(String) -> ())
{
var companyFile = ""
companies = ()
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? [] 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 incompanies as! []
{
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 =newCompanyObjas NSDictionary!
{
if let companies = json["RESULTS"] as? NSDictionary
{
if let companiesNew = companies["COMPANIES"] as? []
{
// 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: ?
var updateCompanies:?
var comapnySet = Set(self.companies!)
batchGroup.enter()
queue.async(group: batchGroup)
{
if (addArray.count > 0 )
{
addCompanies = ()
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 = ()
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 = status
}
if let message = json["MESSAGE"] as? String
{
dataDict = 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
{
}
})
}
</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>"</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) -> ()) {
// 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]