我创建了一个调度组,其中三个并发队列正在运行,然后通知组进行更新,这一切都很好,我已经将所有这些都放入了一个带有完成处理程序的函数中。现在我面临的问题是完成处理程序在队列执行完成之前被调用。我该如何解决这个问题,请指教?
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 dataFinalata = 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
{
}
})
}
Best Answer-推荐答案 strong>
你混淆了很多东西。您正在尝试获得通知,但您也在尝试等待。
您的 completion() 处理程序和标有 的代码
//Below code is executed before queue completion"
在您的通知 block 之外被调用/运行...
AFAICS,没有理由在 loadCompaniesFromSynch() 中使用 notify 或 wait ,因为您不调用任何异步任务它。
我怎么理解,你想做的是在后台做你繁重的 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
}
希望这会有所帮助。
关于ios - 完成处理程序未按预期与调度组和并发队列一起工作,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/41184178/
|