简体   繁体   中英

Multipeer Connectivity peer to peer with Progress bar.

I have worked on this for some time now! (weeks) Can someone show me where and how to add a Progress or Activity Indicator with a label showing the % complete to a peer to peer connectivity on both the sending and receiving sides.

import UIKit
import MultipeerConnectivity



class ViewController: UIViewController, MCSessionDelegate, MCBrowserViewControllerDelegate,  UINavigationControllerDelegate , UIImagePickerControllerDelegate{



//MARK: - Variables
var myDictionary:NSDictionary = [:]

//Variables for Peer to Peer.
var browser   : MCBrowserViewController!
var assistant : MCAdvertiserAssistant!
var session   : MCSession!
var peerID    : MCPeerID!

//Variables for Peer to Peer.
let imagePicker  = UIImagePickerController()
var imageDataVar: NSData!



//MARK: - Labels
@IBOutlet weak var firstNameLabel: UILabel!
@IBOutlet weak var lastNameLabel:  UILabel!

//MARK: - TextFields
@IBOutlet weak var fistNameTextField: UITextField!
@IBOutlet weak var lastNameTextField: UITextField!

//MARK: - Outlets

@IBOutlet weak var contactImageView: UIImageView!

//MARK: - Buttons
@IBAction func openPortButton(_ sender: AnyObject) {
self.present(self.browser, animated: true, completion: nil)
}

@IBAction func sendButton(_ sender: AnyObject) {
    sendInfo()
 }

@IBAction func getImage(_ sender: AnyObject) {
    chooseImageContact()
 }


//MARK: - ViewDidLoad
override func viewDidLoad() {
    super.viewDidLoad()
    loadPeerToPeer()
}


//MARK: - Functions
func sendInfo() {
    if self.session.connectedPeers.count > 0 {
        let firstNameVar = fistNameTextField.text!
        let lastNameVar = lastNameTextField.text!
            myDictionary = ["itemA" : "\(firstNameVar)", "itemB" : "\    (lastNameVar)", "itemC" : imageDataVar]
        do {
            let data =  NSKeyedArchiver.archivedData(withRootObject:  myDictionary)
            try self.session.send(data, toPeers:  self.session.connectedPeers, with: MCSessionSendDataMode.unreliable)
        } catch let error as NSError {
            let ac = UIAlertController(title: "Send error", message:     error.localizedDescription, preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default,  handler: nil))
            present(ac, animated: true, completion: nil)
        }
    }
}


// Called when a peer sends an NSData to us
func session(_ session: MCSession, didReceive data: Data, fromPeer  peerID: MCPeerID)  {

// This needs to run on the main queue
DispatchQueue.main.async {
    self.myDictionary = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSDictionary

    self.firstNameLabel.text    = self.myDictionary.value(forKey: "itemA") as? String
    self.lastNameLabel.text     = self.myDictionary.value(forKey: "itemB") as? String
    let image                   = self.myDictionary.value(forKey: "itemC") as? NSData
    let newContactImage:UIImage = UIImage(data: image! as Data)!
    let smallPicture            = self.scaleContactImageWith(newContactImage, newSize: CGSize(width: 100, height: 100))
    var sizeOfImage:CGRect      = self.contactImageView.frame
        sizeOfImage.size        = smallPicture.size
    self.contactImageView.frame = sizeOfImage
    self.contactImageView.image = smallPicture
}
}


func browserViewControllerDidFinish(_ browserViewController:   MCBrowserViewController) {
    dismiss(animated: true, completion: nil)
}
func browserViewControllerWasCancelled(_ browserViewController:   MCBrowserViewController) {
    dismiss(animated: true, completion: nil)
}
func browserViewController(_ browserViewController:   MCBrowserViewController, shouldPresentNearbyPeer peerID: MCPeerID,   withDiscoveryInfo info: [String : String]?) -> Bool {
    return true
}

func session(_ session: MCSession, peer peerID: MCPeerID, didChange  state: MCSessionState) {
    switch state {
    case MCSessionState.connected:
        print("Connected: \(peerID.displayName)")
    case MCSessionState.connecting:
        print("Connecting: \(peerID.displayName)")
    case MCSessionState.notConnected:
        print("Not Connected: \(peerID.displayName)")
    }
}

func session(_ session: MCSession, didStartReceivingResourceWithName    resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
}
func session(_ session: MCSession, didFinishReceivingResourceWithName   resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL,   withError error: Error?) {
}
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}



func loadPeerToPeer(){
    self.peerID  = MCPeerID(displayName: UIDevice.current.name)
    self.session = MCSession(peer: peerID, securityIdentity: nil,   encryptionPreference: .required)
    self.session = MCSession(peer: self.peerID)
    self.session.delegate = self
    self.assistant = MCAdvertiserAssistant(serviceType:"VBC-ShareCard",  discoveryInfo:nil, session:self.session)
    self.assistant.start()
    self.browser = MCBrowserViewController(serviceType: "VBC- ShareCard", session: self.session)
    self.browser.delegate = self
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController)  {
    picker.dismiss(animated: true, completion: nil)
}


// Picking the image
func chooseImageContact(){
    let imagePicker            = UIImagePickerController()
        imagePicker.delegate   = self
        imagePicker.sourceType =    UIImagePickerControllerSourceType.photoLibrary
    self.present(imagePicker, animated: true, completion: nil)
}


//Scalling the image
func scaleContactImageWith(_ image:UIImage, newSize:CGSize)->UIImage{
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height:  newSize.height))
    let newContactImage:UIImage =  UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    return newContactImage
}

func imagePickerController(_ picker: UIImagePickerController,   didFinishPickingMediaWithInfo info: [String : Any]) {

    //This gets the Contact image inside the imagePickerController
    let pickedImage:UIImage     =    info[UIImagePickerControllerOriginalImage] as! UIImage
    let smallPicture            = scaleContactImageWith(pickedImage,   newSize: CGSize(width: 100, height: 100))
    var sizeOfImage:CGRect      = contactImageView.frame
        sizeOfImage.size        = smallPicture.size
        contactImageView.frame  = sizeOfImage
        picker.dismiss(animated: true, completion: nil)
        contactImageView.image  = smallPicture as UIImage
    let test : Data             =  UIImagePNGRepresentation(smallPicture)!
        imageDataVar            = test as NSData!
}

}

You should use the MCSessionDelegate function which you have implemented.

func session(MCSession, didStartReceivingResourceWithName: String, fromPeer: MCPeerID, with: Progress)

You can use the Progress object to either cancel the transfer or find out how much progress has been made.

Whilst sending data you can use the completion handler of the function used to send data.

func sendResource(at resourceURL: URL, 
     withName resourceName: String, 
       toPeer peerID: MCPeerID, withCompletionHandler completionHandler: ((Error?) -> Void)? = nil) -> Progress?

Again the Progress object can be used to track the progress.

On a seperate note, please can you let me know if you have tried using MultipeerConnectivity on iOS 10 and if it works for you. I've been trying the whole of last week but it is not connecting with the peer. (Thanks)

Hope this helps.

Cheers

My work around.

  //New Variable for spinner.
  var spinnerOnOff = "" 

  //New Function to start, stop, hide and unhide spinner.
  func spin(){
    if spinnerOnOff == "on"{
       activityIndicatorOutlet.isHidden = false
       activityIndicatorOutlet.startAnimating()
    }else{
       activityIndicatorOutlet.isHidden = true
       activityIndicatorOutlet.stopAnimating()
    }
}


//Updated function. (code block will ran "Quickly")
func sendInfo() {
    if self.session.connectedPeers.count > 0 {
        let firstNameVar = fistNameTextField.text!
        let lastNameVar = lastNameTextField.text!
            myDictionary = ["itemA" : "\(firstNameVar)", "itemB" : "\     (lastNameVar)", "itemC" : imageDataVar]
        do {
            let data =  NSKeyedArchiver.archivedData(withRootObject:   myDictionary)
            try self.session.send(data, toPeers:   self.session.connectedPeers, with: MCSessionSendDataMode.unreliable)
        } catch let error as NSError {
            let ac = UIAlertController(title: "Send error", message:        error.localizedDescription, preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default,    handler: nil))
            present(ac, animated: true, completion: nil)
        }
    }

    //New. Stop spinner when function Executes.
    spinnerOnOff = "off"  
    spin()

}

//Updated Function.
func session(_ session: MCSession, didReceive data: Data, fromPeer  peerID: MCPeerID)  {

// This needs to run on the main queue
DispatchQueue.main.async {
    self.myDictionary = NSKeyedUnarchiver.unarchiveObject(with: data) as!   NSDictionary

    self.firstNameLabel.text    = self.myDictionary.value(forKey: "itemA") as? String
    self.lastNameLabel.text     = self.myDictionary.value(forKey: "itemB") as? String
    let image                   = self.myDictionary.value(forKey: "itemC") as? NSData
    let newContactImage:UIImage = UIImage(data: image! as Data)!
    let smallPicture            =    self.scaleContactImageWith(newContactImage, newSize: CGSize(width: 100,  height: 100))
    var sizeOfImage:CGRect      = self.contactImageView.frame
        sizeOfImage.size        = smallPicture.size
    self.contactImageView.frame = sizeOfImage
    self.contactImageView.image = smallPicture

    //New. Stop spinner when data is received.
    self.spinnerOnOff = "off"
    self.spin()

}
}
    //Updated Function
    func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {

    switch state {
    case MCSessionState.connected:

        //New. Start spinner on connected phone.
        DispatchQueue.main.async {          
        self.spinnerOnOff = "on"
        self.spin()
        }

        print("Connected: \(peerID.displayName)")
    case MCSessionState.connecting:

        //New. Start spinner on sender phone.
        DispatchQueue.main.async {
        self.spinnerOnOff = "on"
        self.spin()
        }

        print("Connecting: \(peerID.displayName)")
    case MCSessionState.notConnected:

        //New. Stop when disconnected.
        DispatchQueue.main.async {
        self.spinnerOnOff = "off"
        self.spin()
        }

        print("Not Connected: \(peerID.displayName)")
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM