我使用GCD DispatchWorkItem将一些数据发送到Firebase。我首先将图片发送到Firebase存储并在完成处理程序中接收元数据并将其转换为URL,然后转换为字符串。然后我将该url字符串发送到Firebase数据库。我已经测试了我的GCD方法,然后去了后台,注释掉了第一个调用,这样它就会触发问题,并且还会注释掉第二个调用,这样它就会触发问题,然后一切正常。但是,如果由于用户关闭手机而在执行某个网络呼叫时应用停止,我不确定该怎么办。
我将分步解释:
用户按下sendButton,图像被初始化,然后转换为数据。我有一个全局标志,按下按钮时设置为true。它最初被设置为false,如果出现问题或者它到达secondCall的回调,它将被设置为false。
firstCall是一个DispatchWorkItem(DWI),它接收数据并将其发送到FB存储。
在firstCall结束时,我调用firstCall.perform()以便它可以运行。就在下面,我将一个problemCall初始化为一个在10秒内触发的DWI。如果它触发它将取消firstCall,将global标志更改为false,并显示错误警报。
在firstCall的回调中,如果成功到达,我取消问题电话。
假设firstCall在不到10秒内完成,我就将secondCall初始化为DWI。
在secondCall中我从firstCall获取url并将其发送到FB数据库。
在secondCall的底部我调用secondCall.perform(),现在它可以运行了。就在下面,我再次使用另一个将在20秒内触发的DWI初始化problemCall。如果它触发它将取消secondCall,将全局标志更改为false,并显示警告
在secondCall的回调中,如果成功到达,我取消问题调用,然后运行self.wereGoodNowDoSomething(),并将globe类更改为false。
ACLASS:
let storageRef = myFbStorageRef()
let dbRef = myFbDatabaseRef()
var firstCall: DispatchWorkItem?
var secondCall: DispatchWorkItem?
var problemCall: DispatchWorkItem?
var myImage: UIImage?
var imageUrlStr: String?
var someGlobalCass: SomeGlobalClass()
@IBAction fileprivate func sendButtonPressed(_ sender: UIButton){
self.someGlobalClass.flag = true
self.myImage = someFuncReturnsSomeImage()
if let convertImage = self.myImage, let imageData = UIImageJPEGRepresentation(convertImage, 0.2){
self.firstCall = DispatchWorkItem{ [weak self] in
self?.storageRef.putData(imageData, metadata: nil, completion: {
(metadata, error) in
//if it gets here in less then 10 secs cancel the problemCall for the firstCall
self.problemCall?.cancel()
if let url = metadata?.downloadURL()?.absoluteString{
self.imageUrlStr = url
}
self.secondCall = DispatchWorkItem{ [weak self] in
var imageDict = [String:Any]()
imageDict.updateValue(self.imageUrlStr, forKey: "imageUrlStr")
self?.dbRef.updateChildValues(imageDict(), withCompletionBlock: {
(error, ref) in
//if it gets here in less then 10 secs cancel the problemCall for the secondCall
self.problemCall?.cancel()
//if it reaches here were good
self.wereGoodNowDoSomething()
self?.someGlobalClass.flag = false
}
}
/*>>>>>>APP GETS SHUT HERE DOWN BEFORE secondCall CAN PERFORM<<<<<<*/
self.secondCall?.perform()
//if the secondCall doesn't complete in 20 secs then cancel it
self.problemCall = DispatchWorkItem{ [weak self] in
self?.secondCall?.cancel()
self?.someGlobalClass.flag = false
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 20, execute: self.problemCall!)
}
self.firstCall.perform()
//if the firstCall doesn't run in 10 secs then cancel it
self.problemCall = DispatchWorkItem{ [weak self] in
DispatchQueue.main.async {
self?.firstCall?.cancel()
self?.someGlobalClass.flag = false
//show alert for error
return
}
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: self.problemCall!)
}
}
当firstCall完成时,如何处理在第6步和第7步之间关闭的应用程序,第二次调用正在运行,但它永远不会完成,而且因为应用程序关闭,problemCall永远不会触发?
问题是我现在将图像数据放在FB Storage中,url字符串从未被发送到数据库,并且当全局标志从未到达将其更改回的点时,现在将设置为true假
在回调中我排除了if错误!= nil。我在那里取消了problemCall,将全局标志设置为false,然后显示警告。