Reputation: 21
I'm working on an app that requires Multipeer Connectivity and have run into a peculiar problem.
If I set the MCSessionDelegate my devices won't connect. If I don't set the MCSession delegate my devices connect, but I can't receive responses.
Without a delegate I can tell they are connecting because printing out the MCSession.connectedPeers
array shows the other peers.
A simplified version of the class that handles connection and communication is shown below.
import UIKit
import MultipeerConnectivity
class ConnectionManager: NSObject, MCSessionDelegate, MCNearbyServiceBrowserDelegate, MCNearbyServiceAdvertiserDelegate {
// MARK: - Properties
var advertiser: MCNearbyServiceAdvertiser!
var browser: MCNearbyServiceBrowser!
var peerID: MCPeerID!
var session: MCSession!
// MARK: - Lifecycle
override init() {
super.init()
peerID = MCPeerID(displayName: UIDevice.current.name)
advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: "testconnect")
advertiser.delegate = self
browser = MCNearbyServiceBrowser(peer: peerID, serviceType: "testconnect")
browser.delegate = self
session = MCSession(peer: peerID, securityIdentity: nil, encryptionPreference: .optional)
session.delegate = self
}
deinit {
advertiser.stopAdvertisingPeer()
browser.stopBrowsingForPeers()
print("Stopping connection service...")
}
// MARK: Session Delegate
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
}
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
switch state {
case .connected:
print("\(peerID.displayName) connected")
case .notConnected:
print("\(peerID.displayName) not connected")
case .connecting:
print("\(peerID.displayName) connecting")
}
}
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, didReceiveCertificate certificate: [Any]?, fromPeer peerID: MCPeerID, certificateHandler: @escaping (Bool) -> Void) {
}
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
}
// MARK: - Nearby Advertiser Delegate
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {
print("\(#function): \(error.localizedDescription)")
}
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
print("Invitation received from \(peerID.displayName)")
invitationHandler(true, session)
}
// MARK: - Nearby Browser Delegate
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
print("Lost peer \(peerID.displayName)")
}
func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
print(error.localizedDescription)
}
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String: String]?) {
print("Found peer \(peerID.displayName)")
browser.invitePeer(peerID, to: session, withContext: nil, timeout: 30)
}
}
If I comment out the session.delegate = self
line the devices connect, as shown by printing the session.connectedPeers. Leave it as is, and the devices attempt to connect, but fail.
I have also created a very simple app that demonstrates the problem here, https://github.com/StagasaurusRex/MultiPeerConnectionTest
Simply have both devices advertise, then have one of them browse, the devices will attempt to connect and you can see that with the delegate they fail but without it they succeed. Verify this by printing the connections.
Does anyone have any idea what is going on? I would greatly appreciate some help, I've been tearing my hair out trying to figure it out.
Thanks.
Upvotes: 1
Views: 1401
Reputation: 21
Well I figured it out.
I had an empty implementation of session(_:didReceiveCertificate:fromPeer:certificateHandler:) which was rejecting the connection as it wasn't calling the certificateHandler with true.
Removing that empty function fixed my issue and allowed my devices to connect.
Upvotes: 1