Search code examples
iosswiftprogressmultipeer-connectivity

Unable to display data transfer progress in multipeer connectivity framework


I'm trying to print the progress of data transfer while using multipeer connectivity. The progress information is available on the receiver side, in the didStartReceivingResourceWithName method and on the sender side, in the sendResource method. Here is how I have implemented the receiver side:

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
        DispatchQueue.main.async {
            print (progress)
        }
    }

And here is how I implemented the sender side:

func sendFileAction()->Progress{
        var filePath = Bundle.main.url(forResource: "10MO", withExtension: "file")
        if mcSession.connectedPeers.count > 0 {

            do {
                let data =  try Data(contentsOf: filePath!)
                fileTransferProgressInSender = mcSession.sendResource(at: filePath!, withName: "filename", toPeer: mcSession.connectedPeers[0]) { (error) -> Void in
                    DispatchQueue.main.async {
                        if error != nil {
                            print("Sending error: \(String(describing: error))")
                        }else{
                            print("sendAFile with no error "+"filename")
                        }
                    }
                }
            }
            catch let error as NSError {
                let ac = UIAlertController(title: "Send file error", message: error.localizedDescription, preferredStyle: .alert)
                ac.addAction(UIAlertAction(title: "OK", style: .default))
                present(ac, animated: true)
            }
        }
        return(fileTransferProgressInSender)
    }

The receiver function does display the progress only once, at the beginning.

<NSProgress: 0x1c0133740> : Parent: 0x0 / Fraction completed: 0.0000 / Completed: 0 of 10485760  

And I can't figure out where I can call the return of sendFileAction to display the progress on the sender side.

Any help please? Thanks.

Edit: I tried with the following code:

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
        startTime = Date()

        DispatchQueue.main.async {
            self.endTransfer = false
            self.sendProgressBar.progress = 0.0
            self.updateProgress(progress: progress)
        }
    }

func updateProgress(progress:Progress){
        DispatchQueue.main.async {
            while !self.endTransfer {
                print (progress.fractionCompleted)
                self.sendProgressBar.progress = Float(progress.fractionCompleted)
            }
        }
    }

While the print gives real progress in the console, the progress bar jumps from 0 to 1 (reaches 1 before the print does).

What am I doing wrong?

Thanks again.


Solution

  • Thanks @CodeBender for the hint. Indeed, I needed a timer. So here is how I did:

    func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
            startTime = Date()
            self.receptionProgress = progress
            DispatchQueue.main.async {
                self.receptionTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.updateReceptionProgress), userInfo: nil, repeats: true)
                self.receptionTimer.fire()
            }
        }
    

    And the corresponding function:

    @objc func updateReceptionProgress(){
            self.receptionProgressBar.progress = Float(self.receptionProgress.fractionCompleted)
            if self.receptionProgress.completedUnitCount >= self.receptionProgress.totalUnitCount{
                self.receptionTimer.invalidate()
            }
        }