Domanda

Mi chiedo se questo quadro di connettività multipiveri è pronto per l'uso nel mondo reale, dato a tutti gli errori che sono stati incontrati dalla Comunità. Penso che lo sto preparando bene, ma tutti gli altri progetti di esempio che ho provato incontrano problemi simili.

Il problema che sto avendo potuto essere legato ad alcuni problemi inerenti a Bonjour o qualcosa del genere, non riesco a capirlo, ma fondamentalmente il problema è il seguente:

    .
  • Ho un MCSession attivo con un numero di pari.
  • Ora, se un dispositivo è in una sessione, e quindi Force si chiude , che "peer" rimane connesso per una quantità indefinita di tempo.
  • Non c'è nulla che posso fare per forzare quell'utente, anche se il metodo browser:lostPeer: è chiamato per quel peer e non viene più visualizzato nemmeno nel browser come "Vicino".
  • Il metodo session:peer:didChangeState: non è richiesto per quel peer.
  • Quando quel peer che forzava la disconnessione torna all'APP, sono nuovamente "trovati" da browser:foundPeer:withDiscoveryInfo:, ma esistono ancora anche nel session.connectedPeers NSarray. Ovviamente non ricevono dati o aggiornamenti sulla sessione ancora e non sono effettivamente collegati.
  • L'unica cosa che sembra funzionare per registrare quel peer originale come MCSessionStateNotConnected nella sessione è riconnettendo che peer alla sessione originale. Quindi c'è una chiamata duplicata a session:peer:didChangeState: dove la nuova istanza del peerid è MCSessionStateConnected e poco dopo la vecchia istanza delle chiamate peerid con MCSessionStateNotConnected.

L'applicazione chat di esempio dimostra questo problema: https://developer.apple. COM / Biblioteca / iOS / SAMPLECODE / MULTIPEEERGROUPCHAT / INTRODUZIONE / INTRO.HTML

Poiché non sembra esserci alcun modo per forzare manualmente rimuovere un peer dalla sessione, cosa dovrei fare? Dovrei provare a ricostruire la sessione in qualche modo?

Questo quadro sembra un po 'di casino, ma sto cercando di riservare il giudizio!

È stato utile?

Soluzione

La mia unica soluzione alternativa a questo tipo di problema è stata quella di avere una relazione 1-1 tra sessioni e pari.Complica l'invio di trasmissioni, ma almeno consente disconnetti e pulizia del livello peer-level attraverso la disconnessione / rimozione della sessione stessa.

Aggiornamento

Per elaborare la mia risposta originale, per poter inviare dati ai peer collegati è necessario mantenere un riferimento alla sessione creata per ciascun peer.Ho usato un dizionario mutabile per questo.

Una volta che l'invito è stato inviato / accettato con una nuova sessione, utilizzare il metodo Delegato MCSession per aggiornare il dizionario:

- (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];
    }
}
.

Tutti i peer possono essere accessibili con un metodo che restituisce tutti i valori del dizionario e a turno tutto connectedPeers (in questo caso uno) per ogni MCSession:

- (NSArray *)allConnectedPeers {

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

}
.

L'invio di dati a un particolare peer o via trasmissione può essere eseguito con un metodo come questo:

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

Altri suggerimenti

Hai provato a disconnettere la sessione prima che la domanda si chiuda?Questo dovrebbe rimuovere correttamente il peer dalla sessione e ripuliare qualsiasi risorsa assegnata per il peer.

In particolare intendo qualcosa come [self.peer disconnect] in applicationWillTerminate:

Ho avuto problemi simili.Sembra che se avessi eseguito la mia app su un dispositivo iOS e collegato a un altro, quindi smettere e rilanciare (ad esempio quando ho reindirizzato da Xcode), allora sono in una situazione in cui ricevo un messaggio collegato e quindi non connessomessaggio un po 'più tardi.Questo mi stava buttando fuori.Ma guardando più attentamente, posso vedere che il messaggio non connesso è effettivamente inteso per un peerido diverso da quello che è collegato.

Penso che il problema qui sia che la maggior parte dei campioni che ho visto solo cura del nome del peerid e trascurare il fatto che è possibile ottenere più peeridi per lo stesso dispositivo / visualizzazione.

Sto controllando prima il displayName e poi verificando che il peerid sia lo stesso, facendo un confronto dei puntatori.

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

...
.

Non ho potuto ottenere la risposta accettata per sempre funzionare, quindi cosa ho fatto invece è avere un timer che avrebbe sparato a ripristinare la connessione quando il browser segnalerà non collegato e non c'erano altri peer collegati.

-(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];
            }
        );
    }
}
...
.

}

È possibile eliminare il peer dal mcbrowsperviewcontroller con il seguente codice in Swift 3:

self.mySession.cancelConnectPeer(self.myPeerID)
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top