iOS multipeer connectivity: how to distinguish equality of peers

iOS’s Multipeer Connectivity (MPC) framework is peer-to-peer.  Peers are equal.  No peers are distinguished from other peers.

Compare to a client-server model, where there is a distinguished server and less distinguished clients.

You can use the MPC framework to build distributed apps, such as chat or multiplayer games.  (But only where the participants are nearby, in a local area.  For remote participants, such as over the internet, you must use some other framework.)

But suppose you want to distinguish one of your players, or simply to know which player initiated the game.  The rest of this post is an educated guess about how to do that.  I haven’t tested it yet.

To be more concrete, in a chat application it is fine for all the peers to be totally equal.  A peer’s own chat posts can bounce back to self and be displayed in the view of the chat posts.  But in a game such as chess, you might want to distinguish one of the peers as white, so that white can go first.

The  MCSession object won’t tell you which peer initiated or invited others.  (An instance of MCSession is a port to a distributed object.  In other words, the ‘session’ is a larger abstract object that all the peers see through an MCSession instance.  The ‘session’ has no ID, only the serviceType string to tell you ‘what the session is for’ e.g. ‘playingMyGame’.)  I don’t think the framework guarantees that the list of connected peers is in any particular order.

You can’t tell from the didChangeState (to MCSessionState.Connected) event.  Whenever some peer joins the session (by accepting an invitation), all peers will receive a didChangeState event.  There is no timestamp on the event.  I don’t think the framework guarantees that the initiator will receive the didChangeState before the acceptor.

But apparently you can tell which peer is the initiator by using the MCAdvertiserAssistantDelegate protocol.  When you create an MCAdvertiserAssistant (to show incoming invitations), you  can configure (initialize) it with a delegate, an object that implements MCAdvertiserAssistantDelegate protocol.  The framework will call the advertiserAssistantDidDismissInvitation() method of the delegate when the user dismisses (accepts or declines) the incoming invitation GUI (dialog.)  The callback doesn’t tell you whether the user accepted or declined the invitation.  But subsequently (? I’m not sure the framework actually guarantees it will come after the invitation is dismissed) you should also get a didChangeState (to MCSessionState.Connected) event.  So you can use a small state machine to tell you that a newly connected event came after an invitation was displayed.  Then you might know that the new peer was the initiator, and that you were the acceptor.  In other words, that you are the less-distinguished peer.  If you receive notice of a newly connected peer, but you did not previously get a callback to advertiserAssistantDidDismissInvitation() , then you know that you are the initiator, more distinguished.

This suggested implementation could be messy, for example you might need to use a timer for a short period of time to wait for a connection, to know whether your user accepted an invitation.

This implementation also might only order two peers (for a two-player game); it doesn’t totally order all the peers for a many-player game. In other words, you might need to implement your own protocol (of messages between peers) to establish a total order among players.

If anyone has already implemented this, or knows a better solution, I am interested.