Search code examples
swiftmultipeer-connectivity

Swift MultipeerConnectivity - invitePeer always ends in a timeout


I'm currently working on a game where I need to connect 2 peers. To do this I have gone through this tutorial. I built the described demo app and it worked like a charm, i.e. I was able to chat between my iPhone 5 and my Macbook Pro. However, now that I'm working on the game application I'm not able to establish a connection anymore. Basically what I do is that I display in a table view all the advertisers. Once one clicks on a given cell, the following code will be executed:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    var peer = appDelegate.mcManager.foundPeers.keys.array[indexPath.row] as MCPeerID

    self.appDelegate.mcManager.joinGame(peer)
}

In the mcManager the joinGame looks like:

func joinGame(peer : MCPeerID){
    // Setup Advertising:
    self.setAdvertiserDiscoveryInfo(self.foundPeers[peer] as! [String:String])
    self.advertiser.startAdvertisingPeer()
    self.appDelegate.isAdvertising = true
    // Create Connection
    self.browser.invitePeer(peer, toSession: self.session, withContext: nil, timeout: self.connectingTimeout)
}

Obviously there are no error messages from XCode. Every code is executed as it should. Even the invitePeer(...) is being executed. But it always ends in a timeout.

I compared the demo app (from the tutorial above) and the game app in the debugger and I noticed one thing, that is that the demo app's browser variable contains an _netServices variable with one key/value pair, whereas the game app doesn't (_netServices is empty).

Currently I have no clue what is wrong, since I heavily base myself on the given tutorial, i.e. there is a lot of copy/paste involved. And since the first demo app is working I don't know what happened.

Just FYI, here is the init() of the mcManager:

override init() {
    super.init()

    peer = MCPeerID(displayName: UIDevice.currentDevice().name)

    session = MCSession(peer: peer)
    session.delegate = self

    browser = MCNearbyServiceBrowser(peer: peer, serviceType: serviceType)
    browser.delegate = self

    advertiser = MCNearbyServiceAdvertiser(peer: peer, discoveryInfo: nil, serviceType: serviceType)
    advertiser.delegate = self

}

Solution

  • I finally found the solution! After I went totally mad, because I did not find any problem, I created a new Project and added step by step the code from the game application. After every step I tested the code.

    Finally I found out, that the problem was the advertiser and its discovery info. When the user creates a game I reinitialize the advertiser with the user generated discovery information. The problem was that after the reinitialization I forgot to put the delegate, i.e.:

    func setAdvertiserDiscoveryInfo(discoveryInfo: Dictionary<String, String>) {
        advertiser = MCNearbyServiceAdvertiser(peer: peer, discoveryInfo: discoveryInfo, serviceType: serviceType)
        advertiser.delegate = self // I forgot this line!
    }
    

    Furthermore, I initialized the discovery info variable as [String : String]. The compiler did not raise any error so I thought it was correct. However the connection was only possible when I changed the discovery information to Dictionary<String, String>.