Frage

Ich frage mich, ob dieses Multipeer-Konnektivitäts-Framework angesichts all der Fehler, auf die die Community gestoßen ist, für den Einsatz in der realen Welt bereit ist.Ich denke, ich richte es richtig ein, aber bei allen anderen Beispielprojekten, die ich ausprobiert habe, treten ähnliche Probleme auf.

Das Problem, das ich habe, hängt möglicherweise mit einem Problem zusammen, das Bonjour innewohnt, oder so, ich kann es nicht herausfinden, aber im Grunde ist das Problem wie folgt:

  • Ich habe eine aktive MCSession mit einer Reihe von Gleichaltrigen.
  • Wenn sich nun ein Gerät in einer Sitzung befindet und dann kraft beendet sich, dieser "Peer" bleibt auf unbestimmte Zeit verbunden.
  • Ich kann nichts tun, um diesen Benutzer zu zwingen, obwohl der browser:lostPeer: methode wird für diesen Peer aufgerufen und wird im Browser nicht einmal mehr als angezeigt "Gelegenen".
  • Der session:peer:didChangeState: methode wird für diesen Peer nicht aufgerufen.
  • Wenn der Peer, den diese Kraft beendet hat, zur App zurückkehrt, werden sie von der App wieder "gefunden browser:foundPeer:withDiscoveryInfo: gibt es aber auch noch in der session.connectedPeers NSArray.Offensichtlich erhalten sie immer noch keine Daten oder Aktualisierungen über die Sitzung und sind nicht wirklich verbunden.
  • Das einzige, was zu funktionieren scheint, um diesen ursprünglichen Peer als zu registrieren MCSessionStateNotConnected zur Sitzung wird dieser Peer erneut mit der ursprünglichen Sitzung verbunden.Dann gibt es einen doppelten Anruf an session:peer:didChangeState: wo die neue Instanz der peerID ist MCSessionStateConnected und kurz darauf ruft die alte Instanz der peerID mit MCSessionStateNotConnected.

Die Beispiel-Chat-Anwendung demonstriert dieses Problem gut: https://developer.apple.com/library/ios/samplecode/MultipeerGroupChat/Introduction/Intro.html

Was soll ich tun, da es anscheinend keine Möglichkeit gibt, das Entfernen eines Peers manuell aus der Sitzung zu erzwingen?Soll ich versuchen, die Sitzung irgendwie neu zu erstellen?

Dieser Rahmen scheint ein bisschen durcheinander zu sein, aber ich versuche, ein Urteil zu behalten!

War es hilfreich?

Lösung

Meine einzige Problemumgehung für diese Art von Problem bestand darin, eine 1: 1-Beziehung zwischen Sitzungen und Peers zu haben.Dies erschwert das Senden von Broadcasts, ermöglicht jedoch zumindest Trennungen und Bereinigungen auf Peer-Ebene durch Trennen / Entfernen der Sitzung selbst.

Update

Um meine ursprüngliche Antwort näher zu erläutern, ist es erforderlich, einen Verweis auf die Sitzung zu pflegen, die für jeden Peer erstellt wurde, um Daten an verbundene Peers senden zu können.Ich habe dafür ein veränderliches Wörterbuch verwendet.

Sobald die Einladung mit einer neuen Sitzung gesendet / angenommen wurde, verwenden Sie die MCSession delegate-Methode zum Aktualisieren des Wörterbuchs:

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

    if (state==MCSessionStateConnected){

        _myPeerSessions[peerID.displayName] = session;

    }
    else if (state==MCSessionStateNotConnected){

        //This is where the session can be disconnected without
        //affecting other peers
        [session disconnect];            

        [_myPeerSessions removeObjectForKey:peerID.displayName];
    }
}

Auf alle Peers kann mit einer Methode zugegriffen werden, die alle Werte des Wörterbuchs und wiederum alle zurückgibt connectedPeers (in diesem Fall eins) für jeden MCSession:

- (NSArray *)allConnectedPeers {

   return [[_myPeerSessions allValues] valueForKey:@"connectedPeers"];

}

Das Senden von Daten an einen bestimmten Peer oder per Broadcast kann mit einer Methode wie dieser erfolgen:

- (void)sendData:(NSData *)data toPeerIDs:(NSArray *)remotePeers reliable:(BOOL)reliable error:(NSError *__autoreleasing *)error {

    MCSessionSendDataMode mode = (reliable) ? MCSessionSendDataReliable : MCSessionSendDataUnreliable;

    for (MCPeerID *peer in remotePeers){

       NSError __autoreleasing *currentError = nil;

       MCSession *session = _myPeerSessions[peer.displayName];
       [session sendData:data toPeers:session.connectedPeers withMode:mode error:currentError];

       if (currentError && !error)
        *error = *currentError;
    }
}

Andere Tipps

Haben Sie versucht, die Sitzung zu trennen, bevor die Anwendung geschlossen wird?Dies sollte den Peer ordnungsgemäß aus der Sitzung entfernen und alle für den Peer zugewiesenen Ressourcen bereinigen.

Konkret meine ich so etwas wie [self.peer disconnect] in applicationWillTerminate:

Ich hatte ähnliche Probleme.Es scheint jedoch, dass ich, wenn ich meine App auf einem iOS-Gerät ausgeführt und mit einem anderen verbunden habe, dann beende und neu starte (z. B. wenn ich von Xcode aus erneut starte), in einer Situation bin, in der ich eine verbundene Nachricht und dann eine nicht verbundene Nachricht erhalte wenig später.Das hat mich umgehauen.Aber wenn ich genauer hinschaue, kann ich sehen, dass die nicht verbundene Nachricht tatsächlich für eine andere peerId gedacht ist als die, die verbunden ist.

Ich denke, das Problem hierbei ist, dass sich die meisten Beispiele, die ich gesehen habe, nur um den Anzeigenamen der peerID kümmern und die Tatsache vernachlässigen, dass Sie mehrere peerIDs für dasselbe Gerät / denselben Anzeigenamen erhalten können.

Ich überprüfe jetzt zuerst den Anzeigenamen und überprüfe dann, ob die peerID dieselbe ist, indem ich einen Vergleich der Zeiger durchführe.

- (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;

...

Ich konnte die akzeptierte Antwort nicht bekommen, um jemals zu funktionieren, also habe ich stattdessen einen Timer verwendet, der ausgelöst wird, um die Verbindung zurückzusetzen, wenn der Browser meldet, dass keine Verbindung besteht und keine anderen verbundenen Peers vorhanden sind.

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

//DebugLog(@"session didChangeState: %ld",state);

if(resetTimer != nil){
    [resetTimer invalidate];
    resetTimer = nil;
}

if(state == MCSessionStateNotConnected){

    [session disconnect];
    [peerSessions removeObjectForKey:peerID.displayName];
    [self removeGuidyPeerWithPeerID:peerID];
    //DebugLog(@"removing all guides from peer %@",peerID);

    if([localSession connectedPeers].count == 0){

        DebugLog(@"nothing found... maybe restart in 3 seconds");
        dispatch_async(dispatch_get_main_queue(), ^{
            resetTimer = [NSTimer
                      scheduledTimerWithTimeInterval:3.0
                      target:self selector:@selector(onResetTimer:)
                      userInfo:nil
                      repeats:NO];
            }
        );
    }
}
...

}

Sie können den Peer mit folgendem Code in Swift 3 aus dem MCBrowserViewController löschen:

self.mySession.cancelConnectPeer(self.myPeerID)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top