3

Bluetooth モードで iPhone ゲームを作成しました。Bluetooth 経由で 1 対 1 でプレイできます。ピッカーの私の実装は次のとおりです。

picker = [[GKPeerPickerController alloc] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
[picker show];

エラーが発生するコードがわからないので、ピッカーと関係のある他のすべてのメソッドのコードも貼り付けます。

- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context {
  NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  NSDictionary *dataDictionary = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:dataString, peer, session, nil] forKeys:[NSArray arrayWithObjects:@"data", @"peer", @"session", nil]];
  [dataString release];
  [self performSelectorOnMainThread:@selector(receivedData:) withObject:dataDictionary waitUntilDone:YES];
}
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker
    sessionForConnectionType:(GKPeerPickerConnectionType)type {
  // Create a new session if one does not already exist
    if (!self.currentSession) {
      self.currentSession = [[[GKSession alloc] initWithSessionID:@"Session" displayName:nil sessionMode:GKSessionModePeer] autorelease];
      self.currentSession.delegate = self;
    }
    return self.currentSession;
  }
  -(void)peerPickerController:(GKPeerPickerController *)pk didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
    self.currentSession = session;
    session.delegate = self;
    [session setDataReceiveHandler:self withContext:nil];
    picker.delegate = nil;
    [picker dismiss];
    [picker autorelease];
  }
  -(void)peerPickerControllerDidCancel:(GKPeerPickerController *)pk {
    picker.delegate = nil;
    [picker autorelease];
    [self.navigationController popViewControllerAnimated:YES];
  }
  // FAIL
  - (void)session:(GKSession *)session didFailWithError:(NSError *)error {
    NSLog(@"error : %@", [error description]);
  }
  // SESSION VIND ANDERE SESSION -> CONNECT
  -(void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
    switch (state) {
      case GKPeerStateConnected:
        NSLog(@"connect met peer %@", [currentSession displayNameForPeer:peerID]);
        [self generateRandomNumberAndSendIt];
        break;
      case GKPeerStateDisconnected:
        NSLog(@"disconnected");
        [self.currentSession disconnectFromAllPeers];
        currentSession = nil;
        [self.navigationController popViewControllerAnimated:YES];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Whoopsie" message:@"The connection failed" delegate:nil cancelButtonTitle:@"Okido" otherButtonTitles:nil];
        [alert show];
        [alert release];
        [super viewDidDisappear:YES];
        break;
      }
    }

受信リクエストを受け入れると、あるデバイスでピッカーが削除され、別のデバイスでエラーが発生することがありますwait_fences: failed to receive reply: 10004003。アラートビュー自体と関係があると思います。このビューに他のアラートビューを設定しました。

皆さんが私を助けてくれることを願っています。

前もって感謝します。

4

2 に答える 2

1

UIAlertView呼び出しをブロックでラップして、メインスレッドで呼び出すようにしてください。

dispatch_async(dispatch_get_main_queue(), ^{
   // Show UIAlertView
}

このような GK を使用したことはありませんが、(多くのネットワーク ベースのライブラリと同様に) メインの GUI スレッド以外のスレッドからコールバックをトリガーできると思います。メインの GUI スレッド以外からユーザー インターフェイスを表示したり操作したりすることは、ほとんどの GUI ライブラリで禁止されており、Cocoa も例外ではありません (ただし、通常は驚くほど寛容です)。

于 2012-07-12T22:34:25.273 に答える
1

いくつかのブレークポイントを設定し、コードがクラッシュする場所をデバッグする必要があります。コードがクラッシュする場所を特定することは誰にも不可能です。コード内の奇妙な部分を指摘して推測するしかありません。エラーは、提供したコードに含まれていない場合もあります。

[super viewDidDisappear:YES];他の誰かが述べたように、非viewDidAppear:メソッドにステートメントを含めるべきではありません。

また、デバッグしている場合は、wait_fences: failed to receive reply: 10004003. すべての例外でブレークポイントが有効になっていることを確認してください。その方法がわからない場合は、次の手順を参照してください。例外をステップ実行し、それがどの行にあるかを調べ、スローされているエラーを調べます。

あなたの[picker autorelease];電話も少し奇妙です。ピッカーを自動解放したい場合は、picker = [[[GKPeerPickerController alloc] init] autorelease];. GameKit デリゲート メソッドに autorelease ステートメントを配置するのは奇妙です。

于 2012-07-12T22:29:59.027 に答える