2011-12-04 18 views
3

私のアプリはGKSessionModePeerでGKSessionを使用します。これは長い間実行されているアプリケーションで、ユーザーはバックグラウンドに戻り、後で戻ってくるはずだから、ピアを任意に接続したり切断したりする必要があります。ほとんどの場合、これはうまく動作します。しかし、ピアが切断すると、didChangeState:GKPeerStateDisconnectedは実際に切断されたデバイスだけでなく、実際にまだ接続されている他のデバイスに対しても、他のデバイスに通知されることがあります。GKSessionピアの切断により、他のピアが切断されて表示される

以下のコードと4つのデバイス(すべてiOS 5)でこの現象を再現できます。すべてが期待どおりになると、デバイスAは、アプリを終了したときに、他のすべてのデバイスに通知を取得し、それらのデバイス上のログ出力は次のようになります。

Service: didChangeState: peer A disconnected (12345)

しかし、しばらくした後、デバイスの接続を切断(例えば、再び)他のデバイスは、切断されなかったデバイスに対して追加のコールバックを取得します。例えば、デバイスCはなるだろう:

Service: didChangeState: peer A disconnected (...) // expected

Service: didChangeState: peer B disconnected (...) // never disconnected

を私は時々切断装置のログにメッセージのこれらの種類を見ています同じ頃、明確ではない、彼らは実際に関連している場合:

dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef

および/または

dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function

これが発生すると、GKSessionは不良状態にあるように見え、正しく接続や切断を処理しなくなります。良い状態に戻るためには、すべてのデバイスでアプリを強制終了し、少し待ってからやり直す必要があります。

バックグラウンドに移動するときにGKSessionを処理するさまざまな方法を試しました(利用可能な設定のみ=いいえ、切断しない、何もしない)。

他の誰かがこの動作に遭遇していますか(それを解決しましたか)?

AppDelegate(アークを使用して)でシンプルREPRO場合:

- (void)startGKSession 
{ 
    self.gkSession = [[GKSession alloc] initWithSessionID:nil displayName:nil sessionMode:GKSessionModePeer]; 
    gkSession.disconnectTimeout = 10; 
    gkSession.delegate = self; 
     gkSession.available = YES; 
} 

- (void)shutdownGKSession 
{ 
    gkSession.available = NO; 
    [gkSession disconnectFromAllPeers]; 
    gkSession.delegate = nil;  
    gkSession = nil; 
    [self.connectedDevices removeAllObjects]; 
} 

- (void)connectToPeer:(NSString *)peerId 
{ 
    [gkSession connectToPeer:peerId withTimeout:10]; 
} 

- (void)session:(GKSession *)session peer:(NSString *)peerId didChangeState:(GKPeerConnectionState)state 
{ 

     switch (state) { 
       case GKPeerStateAvailable: 
      NSLog(@"Service: didChangeState: peer %@ available, connecting (%@)", [session displayNameForPeer:peerId], peerId); 
      [self performSelector:@selector(connectToPeer:) withObject:peerId afterDelay:.5];    
         break; 

       case GKPeerStateUnavailable: 
         NSLog(@"Service: didChangeState: peer %@ unavailable (%@)", [session displayNameForPeer:peerId], peerId); 
         break; 

       case GKPeerStateConnected: 
      NSLog(@"Service: didChangeState: peer %@ connected (%@)", [session displayNameForPeer:peerId], peerId); 
         break; 

       case GKPeerStateDisconnected: 
         NSLog(@"Service: didChangeState: peer %@ disconnected (%@)", [session displayNameForPeer:peerId], peerId); 
         break; 

       case GKPeerStateConnecting: 
         NSLog(@"Service: didChangeState: peer %@ connecting (%@)", [session displayNameForPeer:peerId], peerId); 
         break; 
     } 
} 

- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID 
{ 
    [session acceptConnectionFromPeer:peerID error:nil]; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.connectedDevices = [[NSMutableArray alloc] init]; 
    [self startGKSession]; 

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 
    self.window.rootViewController = self.viewController; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{  
    [self shutdownGKSession]; 
} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    [self startGKSession]; 
} 

@end 

答えて

1

私は、デバイスが互いに「通過」に接続するので、この切断動作が起こっていることをAppleサポートから聞きました。たとえば、デバイスAはデバイスBを介してデバイスCに接続します。デバイスBがドロップすると、デバイスAはすぐにデバイスCの切断と再接続を認識します。これが修正されるかどうか聞いていない。

-1

これは遅すぎるかもしれませんが、サーバー上のセッションモードを GKSessionModePeerからGKSessionModeServerに変更すると、問題が修正されると思います。

ピアは基本的にすべて互いに接続しますが、サーバーは技術的には同じ方法で動作しますが、切断については適切な通知を受け取ります。

関連する問題