Ошибка API Gamekit при принятии входящего запроса

Я сделал игру для iPhone с режимом Bluetooth, вы можете играть 1 на 1 через Bluetooth. Моя реализация для сборщика заключается в следующем:

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, Я думаю, что это как-то связано с самим предупреждением. У меня есть другие оповещения, настроенные в этом представлении.

Я надеюсь, что вы, ребята, можете мне помочь.

Заранее спасибо.

2 ответа

Попробуй завернуть UIAlertView вызывает в блоках для вызова в основном потоке, например

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

Хотя я не использовал GK, как это раньше, я предполагаю, что он (как и многие сетевые библиотеки) может вызывать обратные вызовы из других потоков, кроме основного потока GUI. Представление или даже манипулирование пользовательским интерфейсом не из основного потока GUI - это большая проблема в большинстве библиотек GUI, и Cocoa не является исключением (хотя обычно это удивительно простительно).

Вам нужно установить некоторые точки останова и отладить в случае сбоя кода, никто не может быть уверен в том, где происходит сбой вашего кода, лучшее, что мы можем сделать, это угадать, указав на странности в вашем коде. Ошибка может даже не быть в указанном вами коде.

Как кто-то еще упомянул, у вас точно не должно быть заявления [super viewDidDisappear:YES]; в неviewDidAppear: метод.

Я также предполагаю, что если вы отлаживаете, то в консоли появляется гораздо более полезное сообщение об ошибке, чем wait_fences: failed to receive reply: 10004003, Убедитесь, что вы включили точки останова для всех исключений. Если вы не знаете, как это сделать, вот несколько инструкций. Пройдите через исключение, выясните, в какой строке оно находится, и выясните, какая ошибка выдается.

Ваш [picker autorelease]; звонки тоже немного странные. Если вы хотите автоматически выпустить сборщик, просто сделайте picker = [[[GKPeerPickerController alloc] init] autorelease];, Странно помещать оператор autorelease в методы делегата GameKit.

Другие вопросы по тегам