2010-02-20 14 views
11

Sto lavorando a un'app per iPhone che consentirà connessioni peer-to-peer. Da quello che ho capito, ho la scelta tra l'utilizzo di GKPeerPicker o GKSession. Non mi piace l'idea di usare PeerPicker perché voglio mostrare un'interfaccia personalizzata, così ho deciso di andare con GKSession, e hey, BONUS è che funziona anche su Wi-Fi, mentre il Peer Picker no.GKSession: cosa succede se Bluetooth e Wi-Fi sono disattivati?

OK, quindi il problema è ... cosa succede se l'utente ha sia il Bluetooth che il Wi-Fi disattivati? Nel Peer Picker, viene richiesto di attivare il Bluetooth senza uscire dall'app. GKSession non ce l'ha ... ma aspetta un secondo, sembra che non riesca nemmeno a controllare se Bluetooth è attivo o non programmaticamente!

Carpe Cocoa claims no problem, utilizzare solo il metodo session:didFailWithError: del delegato. Ma, come spiega nei commenti ... non sembra che funzioni più! E nella mia esperienza, concordo.

C'è qualche altro modo per verificare a livello di programmazione se il Bluetooth è attivo? Questo è qualcosa per cui dovrei sfruttare la Raggiungibilità? O è solo un bug che Apple deve ancora risolvere?

Per essere più precisi, sto creando la mia sessione in questo modo:

GKSession *aSession = [[GKSession alloc] initWithSessionID:nil 
                displayName:user.displayName 
                sessionMode:GKSessionModePeer]; 

self.gkSession = aSession; 
[aSession release]; 

self.gkSession.delegate = self; 
self.gkSession.available = YES; 

[self.gkSession setDataReceiveHandler:self withContext:NULL]; 

La classe implementa l'GKSessionDelegate, e so che sta funzionando perché quando ho bluetooth acceso, i metodi delegato vengono chiamati nessun problema. Li ho implementato come tali:

#pragma mark - 
#pragma mark GKSessionDelegate methods 

- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state { 
    if (GKPeerStateAvailable == state) { 
      [session connectToPeer:peerID withTimeout:10]; 
    } else if (GKPeerStateConnected == state) { 
      // gets user 

      NSError *error = nil; 
      [session sendData:user.connectionData 
         toPeers:[NSArray arrayWithObjects:peerID,nil] 
       withDataMode:GKSendDataReliable error:&error]; 
      if (error) 
       NSLog(@"%@",error); 
    } 
} 



- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID { 
    NSError *error = nil; 
    [session acceptConnectionFromPeer:peerID error:&error]; 
    if (error) 
      NSLog(@"%@",error); 
} 

- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error { 
    NSLog(@"%@",error); 
} 

- (void)session:(GKSession *)session didFailWithError:(NSError *)error { 
    NSLog(@"%@",error); 
} 

Nessuna delle dichiarazioni di registro vengono stampati e ho impostato i punti di interruzione in ogni metodo, ma nessuno di loro sono colpiti quando l'utente ha sia Bluetooth e Wi-Fi spento. Speravo che succedesse qualcosa per attivare la sessione: didFailWithError: in modo che potessi chiedere all'utente di attivare il Bluetooth o connettersi a una rete Wi-Fi.

+2

Sembra un errore o forse una richiesta di miglioramento. Dovresti presentare un radar. –

risposta

1

Sono d'accordo con Martin Gordon, ma una soluzione alternativa potrebbe essere quella di utilizzare Apple's reachability.

1

Punto interessante, hai provato a testarlo con Bluetooth OFF e WiFi ON? Recentemente ho scoperto che sebbene il mio programma stesse chiamando questo messaggio "Bluetooth non disponibile", in realtà non stava usando Bluetooth AT ALL, ma si stava connettendo tramite la mia rete WiFi. Non conosco un modo per forzare GKSession in una connessione Bluetooth senza utilizzare l'oggetto PeerPicker di Apple, ma l'oggetto PeerPicker consente alle persone di creare le proprie interfacce. Ciò che non sembra consentire è tipi di connessione diversi da Peer, quindi se si desidera un accordo Client/Server non sarà di grande aiuto.

-Ash

0

È possibile accendere Blutooth di programmazione, utilizzando API private di Apple (credo BluetoothManger.h), ma attenzione, causerà il rifiuto nella spinta di Apple App Store.

-1

È necessario utilizzare lo stesso sessionID.

+1

Cosa intendi con questo? Perché? –

0

Secondo la nozione di utilizzo della raggiungibilità di Apple. Come bonus è elencato tra le linee guida per l'invio di Apple App Store.

Non è difficile implementare tanto codice quanto il codice necessario è già stato scritto per te.

Slf ha fornito un collegamento ad un codice sorgente utilizzando la classe Reachability, inoltre, è disponibile un collegamento a Apple Dev's official reachability example.

Tuttavia, assicurarsi di verificare la connettibilità in modo asincrono.

Lo sto usando nella mia app e anche se non è la soluzione migliore, almeno notifica all'utente che lui/lei ha bisogno di regolare le impostazioni di connessione o che nessuna rete esiste.

2

Ora in iOS 5, questo può essere raggiunto in questo modo:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil]; 
NSMutableArray * discoveredPeripherals = [NSMutableArray new]; 
CBCentralManager * manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 
[manager scanForPeripheralsWithServices:discoveredPeripherals options:options]; 
[manager stopScan]; 

Ciò richiede che si importa il quadro CoreBluetooth in iOS 5. Se il bluetooth è spento, il sistema farà apparire una visione avviso che sarà offri la possibilità di attivare il bluetooth. Altrimenti, se trova una periferica, chiamerà un metodo delegato corrispondente, ma se non c'è nulla in quell'implementazione non è necessario preoccuparsene.

Problemi correlati