2013-09-26 6 views
5

Я пытаюсь найти follow the WWDC talk, чтобы узнать о структуре MultipeerConnectivity. После многих ложных запусков браузер (ы) показывает сверстников, а приглашения выдаются.Multipeer Connectivity: получение приглашения (с использованием встроенного браузера VC)

Но когда я нажимаю «Принять» на одноранговом устройстве, браузер продолжает показывать «Соединение» без конца. Я думал, что MCBrowserViewController позаботился о логике, и я мог расслабиться, пока пользователь браузера не нажал «Отмена» или «Готово», и метод делегата выстрелил. Держу пари, это нечто очевидное, но это ускользает от меня.

Вот что я надеюсь, это соответствующий код. У меня это в AppDelegate. Операторы NSLog в различных методах делегатов вызываются, как я ожидал, кроме, конечно, в browserViewControllerDidFinish:.

Имейте в виду, что браузер и приглашения действительно появляются, поэтому что-то прав!

В @interface ...

@property (strong, nonatomic) MCSession *theSession; 
@property (strong, nonatomic) MCAdvertiserAssistant  *assistant; 
@property (strong, nonatomic) MCBrowserViewController  *browserVC; 

В @implementation

static NSString* const kServiceType = @"eeps-multi"; 

// called from viewDidAppear in the main ViewController 

-(void)  startSession 
{ 
    if (!self.theSession) { 
     UIDevice *thisDevice = [UIDevice currentDevice]; 

     MCPeerID *aPeerID = [[ MCPeerID alloc ] initWithDisplayName: thisDevice.name]; 
     self.theSession = [[ MCSession alloc ] initWithPeer: aPeerID ]; 
     self.theSession.delegate = self; 
    } else { 
     NSLog(@"Session init skipped -- already exists"); 
    } 
} 

// called from viewDidAppear in the main ViewController 

- (void) startAdvertising 
    { 
    if (!self.assistant) { 
     self.assistant = [[MCAdvertiserAssistant alloc] initWithServiceType:kServiceType 
                   discoveryInfo:nil 
                    session:self.theSession ]; 
     self.assistant.delegate = self; 
     [ self.assistant start ]; 
    } else { 
     NSLog(@"Advertiser init skipped -- already exists"); 
    } 
} 

// called from the main ViewController in response to a button press 

- (void) startBrowsing 
{ 
    if (!self.browserVC){ 
     self.browserVC = [[MCBrowserViewController alloc] initWithServiceType:kServiceType 
                     session:self.theSession]; 
     self.browserVC.delegate = self; 
    } else { 
     NSLog(@"Browser VC init skipped -- already exists"); 
    } 

    [ self.window.rootViewController presentViewController:self.browserVC animated:YES completion:nil]; 
} 

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

ответ

16

Благодаря комментаторами за отличные предложения, которые привели к моему найти свою собственную ошибку. И вот он:

Если вы реализуете метод MCSessionDelegatesession:didReceiveCertificate:fromPeer:certificateHandler, он перехватит попытку сверстника подключиться к сеансу. Вы должны либо явно одобрить это соединение в этом методе, либо прокомментировать его.

Деталь и уроки:

В дополнении к коду я показал, я сделал реализацию короткой различных методов делегата. Один MCSessionDelegate метод это один:

- (void)   session:(MCSession *)session 
    didReceiveCertificate:(NSArray *)certificate 
       fromPeer:(MCPeerID *)peerID 
     certificateHandler:(void (^)(BOOL))certificateHandler 
{ 

} 

Расширение @ советы Big-O Клэр s выше, я начал смотреть все эти методы делегата, на всякий случай. И этот выстрелил, когда сверстник нажал кнопку «Принять» в пользовательском интерфейсе AdvertiserAssistant.

Этот метод дает вам возможность решить, является ли эксперт законным и не подключается (используя certificateHandler:), если вы этого не хотите. Apple говорит,

Ваше приложение должно проверить сертификат ближайшего партнера, а затем решить, следует ли доверять этому сертификату. После принятия этого решения ваше приложение должно вызвать предоставленный блок certificateHandler, передав либо ДА (чтобы доверять ближайшему сверстнику), либо НЕТ (чтобы отклонить его).

Кроме того, вы получите эту подсказку:

Важная: Рамки подключения multipeer не делает никаких попыток проверки достоверности одноранговой при условии идентичности или сертификаты в любом случае. Если ваш делегат не реализует этот метод, все сертификаты принимаются автоматически.

Когда я прокомментировал этот метод, соединения прошли - и эта проблема была решена по крайней мере.

+0

Большое вам спасибо, это спасло меня от часов отладки. Я просто бросил все методы делегата там, чтобы реализовать их позже, и даже не знал о didReceiveCertificate. – cargath

1

Я сам не пошел по пути MCBrowserViewController при работе с новой каркасной картой MC, но из слайда 51 презентации WWDC это похоже на то, что browserViewControllerDidFinish: вызывается только тогда, когда пользователь нажимает. Таким образом, этот обратный вызов, вероятно, не там, где проблема заключается в том, что ваш сверстник все еще отображается как «Подключение ...».

Мне интересно, нужно ли подключать своих одноранговых узлов к сеансу вручную. Вы уже устанавливаете делегата MCSession, поэтому я предполагаю, что вы реализуете session:peer:didChangeState. Установите контрольную точку и посмотрите, когда MCSessionState - MCSessionStateConnected. Единственное, что я не уверен в том, что вам нужно вручную обрабатывать это на стороне рекламодателя, стороне браузера или и то, и другое. Если бы вы могли понять, на каком этапе инфраструктура перестанет обрабатывать его, это будет полезно.

+0

Хорошая идея, поэтому обновление: когда я больше смотрю на вызовы делегатов (и реализую предложение @Alla ниже), я вижу, что я получаю 'didChangeState' до ** не подключенного **, когда устройство отклоняет соединение, но никаких изменений, когда он его принимает. Так что я все еще озадачен (и все еще смотрю). Любые предложения приветствуются! –

+0

Я тоже в этом пункте, и мой подход заключается в установке статического необязательного имени currentSession. В игре я ссылаюсь на этот объект для отправки пакетов данных. Таким образом, когда отчеты сеанса не подключены, я могу установить это на nil, и игра может обработать сбои сетевого подключения изящно. Таким образом, я никогда не ссылаюсь на сеанс браузера или рекламную сессию напрямую. – FrostyL

3

У меня была такая же проблема, и оказалось, что я использовал один и тот же сеанс как для браузера, так и для рекламодателя. дробить сессии, но убедитесь, что ServiceType то же самое, и он будет работать как шарм

- (void) setUpMultipeer{ 
    // Setup Peer ID 
    self.myPeerID = [[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name]; 

    // Setup Sessions 
    self.advertiseSession = [[MCSession alloc] initWithPeer:self.myPeerID]; 
    self.advertiseSession.delegate = self; 

    self.browserSession = [[MCSession alloc] initWithPeer:self.myPeerID]; 
    self.browserSession.delegate = self; 


    // Setup BrowserVC 
    self.browserVC = [[MCBrowserViewController alloc] initWithServiceType:@"SERVICE_TYPE" session:self.browserSession]; 
    self.browserVC.delegate = self; 

    // Setup Advertiser 
    self.advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:@"SERVICE_TYPE" discoveryInfo:nil session:self.advertiseSession]; 
    [self.advertiser start]; 
} 
+0

Спасибо! попробовал, и это не сработало, но помогло мне найти актуальную проблему (см. ниже). Когда работа открылась, я вернулся и попробовал одну сессию, и пока она работает нормально. Конечно, я все еще получаю открытие для работы, поэтому мне может понадобиться ваше предложение в ближайшее время. Я напишу отчет, когда все будет развито. :) –

+1

этот работал для меня, использовал учебник в [appcoda] (http://www.appcoda.com/intro-multipeer-connectivity-framework-ios-programming/), и он использовал тот же сеанс для рекламы и связь, кнопка «done» никогда не срабатывала. – Deano

 Смежные вопросы

  • Нет связанных вопросов^_^