3

我做了一个蓝牙模式的iPhone游戏,你可以通过蓝牙玩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

您需要设置一些断点并调试代码崩溃的位置,任何人都无法确定您的代码崩溃的位置,我们能做的最好的就是通过指出代码中的异常来猜测。该错误甚至可能不在您提供的代码中。

正如其他人提到的那样,您绝对不应该[super viewDidDisappear:YES];在非viewDidAppear:方法中使用该语句。

我还猜测,如果您正在调试,那么控制台中的错误消息会比wait_fences: failed to receive reply: 10004003. 确保您已对所有异常启用断点。如果您不知道该怎么做,这里有一些说明。逐步检查异常,找出它在哪一行,并找出抛出了什么错误。

你的[picker autorelease];电话也有点奇怪。如果您想自动释放选择器,只需执行picker = [[[GKPeerPickerController alloc] init] autorelease];. 将 autorelease 语句放在 GameKit 委托方法中是很奇怪的。

于 2012-07-12T22:29:59.027 回答
1

尝试将您的UIAlertView调用包装在块中以在主线程上调用,例如

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

虽然我以前没有像这样使用过 GK,但我猜它(就像许多基于网络的库一样)可以触发来自除主 GUI 线程之外的其他线程的回调。在大多数 GUI 库中,从主 GUI 线程之外呈现甚至操作用户界面是一个很大的禁忌,Cocoa 也不例外(尽管它通常令人惊讶地宽容)。

于 2012-07-12T22:34:25.273 回答