I am trying to establish a connection between two iOS devices using multiplier connectivity framework. I am able to find the nearby devices and add them to an array. What I want to do is, allow a user to see all nearby connections and tap on anyone to connect with. For example, I find two nearby available Peers PeerA and PeerB. If I tap on PeerA then it should send an invite to PeerA. I am doing all of this on custom UI. So what happens is when I send the invite to any peer, the peer gets disconnected & the below function gets called.
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
print("Peer lost \(peerID.displayName)")
if let p = self.availablePeers[peerID.displayName] as? CustomPeer{
self.availablePeers[peerID.displayName] = nil
print("Remove from list")
}
print("Lost Peer")
}
Here is my complete connection.swift file that have to logic to connect with peers.
// Connection.swift
// Prevue
//
// Created by Prevue on 29/08/2022.
//
import Foundation
import MultipeerConnectivity
class CustomPeer{
var info: [String: Any]?
var peerID: MCPeerID!
}
class Connection: NSObject{
static let ServiceType = AppStrings.ConnectionServiceType
var peerID: MCPeerID!
var session: MCSession!
var advertiser: ServiceAdvertiser!
var browser: BrowserService!
var availablePeers = [String: CustomPeer]()
var didReceiveFrame: ((UIImage)-> Void)?
// just for testing.
func startDiscoveryAndAdvertising(with displayName: String){
peerID = MCPeerID(displayName: displayName)
var info = ["name": displayName, "id": displayName + "_" + String(Int.random(in: 1..<400)), "email": displayName + "@gmail.com"]
self.advertiser = ServiceAdvertiser(peerID: peerID, serviceType: "Prevue", discoverInfo: info, delegate: self)
// advertiser
self.session = MCSession(peer: peerID, securityIdentity: nil, encryptionPreference: .none)
self.browser = BrowserService(peerID: peerID, serviceType: "Prevue", delegate: self)
advertiser.advertiser.startAdvertisingPeer()
browser.browser.startBrowsingForPeers()
}
func startDiscoveryAndAdvertising(with user: Profile){
peerID = MCPeerID(displayName: "\(user.id)")
var info = ["name": user.name, "id": String(user.id), "email": user.email]
self.advertiser = ServiceAdvertiser(peerID: peerID, serviceType: "Prevue", discoverInfo: info, delegate: self)
// advertiser
self.session = MCSession(peer: peerID, securityIdentity: nil, encryptionPreference: .none)
self.browser = BrowserService(peerID: peerID, serviceType: AppStrings.ConnectionServiceType, delegate: self)
advertiser.advertiser.startAdvertisingPeer()
browser.browser.startBrowsingForPeers()
}
func sendData(data: Data){
guard let session = self.session else{
return
}
do{
try session.send(data, toPeers: self.session.connectedPeers, with: .reliable)
}
catch let error {
}
}
func sendInvite(to user: Profile){
guard let customPeer = self.availablePeers["\(user.id)"] as? CustomPeer, let peerID = customPeer.peerID else{
return
}
guard let user = UserDefaultsService.getProfileDataFromDefaults()?.profile else{
return
}
let d = ["user_id": user.id, "name": user.name, "persona": currentPersona.rawValue]
as [String : Any]
self.browser.browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: TimeIntervals.Interval0)
}
func isUserReachable(user: Profile)-> CustomPeer?{
print("Available peers ")
print(self.availablePeers)
if let p = self.availablePeers["\(user.id)"] as? CustomPeer{
return p
}
return nil
}
}
extension Connection: MCSessionDelegate{
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
switch state {
case .connected: print ("connected \(peerID)")
case .connecting: print ("connecting \(peerID)")
case .notConnected: print ("not connected \(peerID)")
default: print("unknown status for \(peerID)")
}
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
if let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String:Any] {
// first check for captured photo
if let photoData = dict["capturedPhoto"] as? Data, let image = UIImage(data: photoData) {
}
else{
guard let imageData = dict["image"] as? Data else {
return
}
guard let image = UIImage.init(data: imageData, scale: 2.0) else {
return
}
if self.didReceiveFrame != nil{
self.didReceiveFrame!(image)
}
print(peerID.displayName)
}
}
else{
let commandString = String.init(data: data, encoding: String.Encoding.utf8)
if commandString == "raiseFramerate" {
} else if (commandString == "lowerFramerate") {
}
}
}
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
}
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 browserViewControllerDidFinish(_ browserViewController: MCBrowserViewController) {
}
func browserViewControllerWasCancelled(_ browserViewController: MCBrowserViewController) {
}
}
//Browser delegate
extension Connection: MCNearbyServiceBrowserDelegate{
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
print("Peer available \(peerID.displayName)")
print(info)
let p = MCPeerID(displayName: peerID.displayName)
var customPeer = CustomPeer()
customPeer.info = info
customPeer.peerID = p
self.availablePeers[p.displayName] = customPeer
print("Found Peer \(p.displayName)")
}
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
print("Peer lost \(peerID.displayName)")
if let p = self.availablePeers[peerID.displayName] as? CustomPeer{
self.availablePeers[peerID.displayName] = nil
print("Remove from list")
}
print("Lost Peer")
}
}
extension Connection: MCNearbyServiceAdvertiserDelegate{
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
// when a peer sends an invitation to connect. We show the custom dialogue here
if let d = context{
do{
let json = try JSONSerialization.jsonObject(with: d) as? [String: Any]
print(json)
print("Someone wants to connect")
}
catch let error{
print(error.localizedDescription)
}
}
}
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {
NSLog("%@", "didNotStartAdvertisingPeer: \(error)")
}
}