Swift iOS-如果因为电话关机而关闭应用程序,如何处理GCD向Firebase发送数据?

时间:2017-08-14 20:27:28

标签: ios swift firebase asynchronous grand-central-dispatch

我使用GCD DispatchWorkItem将一些数据发送到Firebase。我首先将图片发送到Firebase存储并在完成处理程序中接收元数据并将其转换为URL,然后转换为字符串。然后我将该url字符串发送到Firebase数据库。我已经测试了我的GCD方法,然后去了后台,注释掉了第一个调用,这样它就会触发问题,并且还会注释掉第二个调用,这样它就会触发问题,然后一切正常。但是,如果由于用户关闭手机而在执行某个网络呼叫时应用停止,我不确定该怎么办。

我将分步解释:

  1. 用户按下sendButton,图像被初始化,然后转换为数据。我有一个全局标志,按下按钮时设置为true。它最初被设置为false,如果出现问题或者它到达secondCall的回调,它将被设置为false。

  2. firstCall是一个DispatchWorkItem(DWI),它接收数据并将其发送到FB存储。

  3. 在firstCall结束时,我调用firstCall.perform()以便它可以运行。就在下面,我将一个problemCall初始化为一个在10秒内触发的DWI。如果它触发它将取消firstCall,将global标志更改为false,并显示错误警报。

  4. 在firstCall的回调中,如果成功到达,我取消问题电话。

  5. 假设firstCall在不到10秒内完成,我就将secondCall初始化为DWI。

  6. 在secondCall中我从firstCall获取url并将其发送到FB数据库。

  7. 在secondCall的底部我调用secondCall.perform(),现在它可以运行了。就在下面,我再次使用另一个将在20秒内触发的DWI初始化problemCall。如果它触发它将取消secondCall,将全局标志更改为false,并显示警告

  8. 在secondCall的回调中,如果成功到达,我取消问题调用,然后运行self.wereGoodNowDoSomething(),并将globe类更改为false。

  9. 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,然后显示警告。

0 个答案:

没有答案