Reconnecting to disconnected peers Reconnecting to disconnected peers ios ios

Reconnecting to disconnected peers


I was having the same problem, and it seems to have been related to my app browsing and advertising at the same time, and two invitations being sent/accepted. When I stopped doing this and let one peer defer to the other for invitations the devices stayed connected.

In my browser delegate I'm checking the hash value of the discovered peer's displayName and only sending an invitation if my peer has a higher hash value:

Edit

As pointed out by @Masa the hash value of an NSString will be different on 32 and 64 bit devices, so it's safer to use the compare: method on displayName.

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info {    NSLog(@"Browser found peer ID %@",peerID.displayName);           //displayName is created with [[NSUUID UUID] UUIDString]    BOOL shouldInvite = ([_myPeerID.displayName compare:peerID.displayName]==NSOrderedDescending);    if (shouldInvite){        [browser invitePeer:peerID toSession:_session withContext:nil timeout:1.0];     }    else {        NSLog(@"Not inviting");    }}

As you say, the documentation is sparse so who knows what Apple really wants us to do, but I've experimented with both sending and accepting invitations using a single session, and also creating a new session for each invitation accepted/sent, but this particular way of doing things has given me the most success.


For anyone interested, I created MCSessionP2P, a demo app that illustrates the ad-hoc networking features of MCSession. The app both advertises itself on the local network and programmatically connects to available peers, establishing a peer-to-peer network. Hat tip to @ChrisH for his technique of comparing hash values for inviting peers.


I liked ChrisH's solution, which reveals the key insight that only one peer should connect to the other peer, not both. Mutual connection attempts results in mutual disconnection (though not that a single-sided connection actually is, counter-intuitively, a mutual connection in terms of status and communication, so that works fine).

However, I think a better approach than one peer inviting is for both peers to invite but only one peer to accept. I use this method now and it works great, because both peers have an opportunity to pass rich information to the other via the context parameter of the invitation, as opposed to having to rely on scant information available in the foundPeer delegate method.

Therefore, I recommend a solution like so:

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info{    [self invitePeer:peerID];}- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL accept, MCSession *session))invitationHandler{    NSDictionary *hugePackageOfInformation = [NSKeyedUnarchiver unarchiveObjectWithData:context];    BOOL shouldAccept = ([hugePackageOfInformation.UUID.UUIDString compare:self.user.UUID.UUIDString] == NSOrderedDescending);    invitationHandler(shouldAccept && ![self isPeerConnected:peerID], [self openSession]);}