2010-02-20 12 views
11

Ich arbeite an einer iPhone-App, die Peer-to-Peer-Verbindungen ermöglicht. Soweit ich weiß, habe ich die Wahl zwischen GKPeerPicker oder der GKSession. Ich mag die Idee nicht, den PeerPicker zu verwenden, weil ich ein benutzerdefiniertes Interface zeigen möchte, also entschied ich mich, mit GKSession zu gehen, und hey, BONUS ist, dass es auch über Wi-Fi funktioniert, während der Peer Picker das nicht tut.GKSession - was passiert, wenn Bluetooth und Wi-Fi ausgeschaltet sind?

OK, also Problem ist ... was ist, wenn der Benutzer sowohl Bluetooth und Wi-Fi ausgeschaltet hat? Im Peer Picker gibt es eine Aufforderung, Bluetooth einzuschalten, ohne die App zu verlassen. GKSession hat es nicht ... aber woah warte eine Sekunde, es scheint, dass ich nicht einmal überprüfen kann, ob Bluetooth an ist oder nicht programmatisch!

Carpe Cocoa claims no problem, verwenden Sie einfach die Methode session:didFailWithError: des Delegierten. Aber, wie es in den Kommentaren erklärt ... das scheint nicht mehr zu funktionieren! Und nach meiner Erfahrung stimme ich zu.

Gibt es eine andere Möglichkeit, programmgesteuert zu prüfen, ob Bluetooth aktiviert ist? Ist das etwas, für das ich die Erreichbarkeit nutzen sollte? Oder ist es nur ein Fehler, den Apple noch beheben muss?

Um genauer zu sein, ich meine Sitzung wie folgt zu erstellen:

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

Die Klasse implementiert die GKSessionDelegate, und ich weiß, dass es funktioniert, weil, wenn ich Bluetooth eingeschaltet haben, werden die Delegatmethoden genannt kein Problem. Ich habe sie als solche umgesetzt:

#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); 
} 

Keiner der Protokollanweisungen gedruckt werden, und ich Haltepunkte in jeder Methode, aber keiner von ihnen sind getroffen, wenn der Benutzer sowohl Bluetooth und Wi-Fi ausgeschaltet. Ich hatte gehofft, dass etwas passieren würde, um eine Sitzung auszulösen: didFailWithError: damit ich den Benutzer auffordern könnte, Bluetooth zu aktivieren oder eine Verbindung zu einem Wi-Fi-Netzwerk herzustellen.

+2

Klingt wie ein Fehler oder möglicherweise eine Verbesserungsanfrage. Sie sollten ein Radar einreichen. –

Antwort

1

Interessanter Punkt, haben Sie versucht, es mit Bluetooth OFF und dem WiFi ON zu testen? Ich habe kürzlich herausgefunden, dass mein Programm zwar die Nachricht "Bluetooth nicht verfügbar" anrief, es aber nicht Bluetooth AT ALL benutzte, sondern sich über mein WiFi-Netzwerk verband. Ich kenne keine Möglichkeit, GKSession in eine Bluetooth-Verbindung zu zwingen, ohne das PeerPicker-Objekt von Apple zu verwenden, aber das PeerPicker-Objekt ermöglicht es Benutzern, ihre eigenen Schnittstellen zu erstellen. Was es anscheinend nicht zulässt, sind andere Verbindungstypen als Peer. Wenn Sie also eine Client/Server-Anordnung wünschen, wird das nicht viel helfen.

-Ash

0

Sie auf Blutooth programmatisch wechseln können, von Apples privaten API (ich glaube BluetoothManger.h), aber vorsichtig sein, wird es Ablehnung in den Apple App Store Push verursachen.

-1

Sie sollten das gleiche sessionID verwenden.

+1

Was meinst du damit? Warum? –

0

Ich zweite der Begriff der Apples Erreichbarkeit zu verwenden. Als Bonus wird es als eine der Apple App Store Einreichungsrichtlinien aufgeführt.

Es ist nicht so schwer zu implementieren entweder so viel von dem Code benötigt wird bereits für Sie geschrieben.

Slf stellte eine Verbindung zu irgendeinem Quellcode her, der die Erreichbarkeitsklasse verwendet, zusätzlich ist hier ein Link zu Apple Dev's official reachability example.

Stellen Sie jedoch sicher, dass Sie die Verbindungsfähigkeit asynchron überprüfen.

Ich benutze es in meiner App und obwohl es nicht die beste Lösung zumindest ist, teilt es dem Benutzer mit, dass er/sie die Verbindungseinstellungen anpassen muss oder dass keine Netzwerke existieren.

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

Dies erfordert, dass Sie den CoreBluetooth Rahmen in iOS 5. importieren Wenn Bluetooth ausgeschaltet ist, wird das System einen Alarm Ansicht Pop-up, das:

2

jetzt in iOS 5 kann dies wie so erreicht werden, bieten Sie die Möglichkeit, Bluetooth einzuschalten. Andernfalls, wenn es ein Peripheriegerät findet, wird es eine entsprechende Delegate-Methode aufrufen, aber wenn es nichts in dieser Implementierung gibt, müssen Sie sich nicht darum kümmern.