2014-01-21 6 views
8

Ich benutze die Mutlipeer Connectivity Framework zum ersten Mal, und ich möchte programmgesteuert (nicht mit den Assistant-Klassen) steuern.iOS Multipeer Connectivity Framework EinladungHandler scheint nicht zu akzeptieren?

Alles funktioniert genau wie beschrieben, wenn ich meinen Code auf zwei separate Geräte bis zu dem Punkt ausgeführt, wenn die ‚Werber‘ den Rückruf delegieren erhalten:

Der Delegierten Rückruf des Browser-Client aufgerufen wird, wenn es den Inserent entdeckt:

-(void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info{ 
    [[[UIAlertView alloc] initWithTitle:@"Peer Found" message:peerID.displayName delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show]; 

    _session = [[MCSession alloc] initWithPeer:_myPeerID]; 
    _session.delegate = self; 

    //connect to the discovered peer. 
    [_browser invitePeer:peerID toSession:_session withContext:nil timeout:30.0]; 
    [_browser stopBrowsingForPeers]; 

}

Dann werden die Delegierten Rückruf-Werbe Client wird aufgerufen, wenn sie die Einladung erhält:

-(void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL, MCSession *))invitationHandler{ 

    //when my code runs, everything looks correct here. 
    //eg. peerID is definitely my 'browser' client's display name etc. 

    _session = [[MCSession alloc] initWithPeer:_myPeerID]; 
    _session.delegate = self; 

    //using a simple version for testing... accept all invites. 
    invitationHandler(YES, _session); 

    //stop advertising now. 
    [_advertiser stopAdvertisingPeer]; 
} 

Nachdem 'invitationHandler (YES, _session)' aufgerufen wurde, scheint die Verbindung zwischen dem 'Browsing'-Client und dem' Advertising'-Client nie hergestellt worden zu sein.

Ich erhalte keine Delegierten Rückrufe (einmal oder zweimal ich erhielt eine MCSessionStateNotConnected) auf den MCSession-Objekten auf jedem Client-Gerät. Ich hätte gedacht, dass ich den Rückruf des MCSession-Delegierten erhalten hätte:

-(void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state; 

Fehle ich etwas? Ist jemand anderes auf dieses Problem gestoßen?

+0

Haben Sie versucht, den Browser und den Werbetreibenden zu verlassen, anstatt sie sofort zu stoppen? – ChrisH

+0

Ja. Hatte leider immer noch das gleiche Verhalten. –

Antwort

9

Es gibt einen Fehler, den Apple offensichtlich kennt.

Dies ist, was zu der Entdeckung geführt: Why does my MCSession peer disconnect randomly?

Sie müssen den folgenden Delegierten Rückruf implementieren, obwohl es als optional in der Dokumentation ...

aufgeführt wird
- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler 
{ 
certificateHandler(YES); 
} 
1

Die „didReceiveCertificate“ Methode delegieren ist optional und wenn Sie es nicht implementieren, wird das Framework annehmen, dass Sie das Zertifikat akzeptieren (beachten Sie, dass das Zertifikat Null sein kann).

Wenn Sie jedoch die Methode implementieren und dann leer lassen, wird der Peer keine Verbindung herstellen, da das Framework erwartet, dass Sie den certificateHandler entweder mit YES oder NO aufrufen.

1

Ich hatte ähnliche Probleme. Es scheint jedoch, dass, wenn ich meine App auf einem iOS-Gerät ausgeführt und verbunden, dann beenden und neu starten (sagen wir, wenn ich von Xcode erneut ausführen), dann bin ich in einer Situation, in der ich eine Connected-Nachricht und dann eine nicht verbundene Nachricht etwas später. Das hat mich abgeworfen. Aber wenn ich genauer hinschaue, kann ich sehen, dass die Nachricht "Nicht verbunden" eigentlich für eine andere Peer-ID gedacht ist als die, die verbunden ist.

Ich denke, das Problem hier ist, dass die meisten Beispiele, die ich gesehen habe, nur interessieren, die der PeerID, und vernachlässigen Sie die Tatsache, dass Sie mehrere PeerIDs für das gleiche Gerät/displayName erhalten können.

Ich überprüfe nun zuerst den displayName und überprüfe dann, dass die PeerID die gleiche ist, indem ich einen Vergleich der Zeiger mache.

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state { 

    MyPlayer *player = _players[peerID.displayName]; 

    if ((state == MCSessionStateNotConnected) && 
     (peerID != player.peerID)) { 
     NSLog(@"remnant connection drop"); 
     return; // note that I don't care if player is nil, since I don't want to 
       // add a dictionary object for a Not Connecting peer. 
    } 
    if (player == nil) { 
     player = [MyPlayer init]; 
     player.peerID = peerID; 
     _players[peerID.displayName] = player; 
    } 
    player.state = state; 

... 
0

Ein anderes Problem, das ich fand (auch in anderen Beispielcodes, ich.e PeerKit) ist das stopAdvertisingPeer direkt nach dem inputHandler (YES) ist wahrscheinlich falsch. Da Sie selbst eine Einladung annehmen, gibt es keine Garantie, dass Sie verbunden sind. Ich denke, es ist besser, AdvertisingPeer nur zu stoppen, wenn verbunden ist.