W.Staggs
W.Staggs

Reputation: 21

MultiPeer Connectivity won't connect when MCSessionDelegate is set

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

Answers (1)

W.Staggs
W.Staggs

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

Related Questions