Multipeer Connectivity: получение приглашения принято (с помощью встроенного в браузер VC)
Я пытаюсь следить за докладом WWDC, чтобы узнать о структуре MultipeerConnectivity. После многих неудачных попыток браузер (-ы) показывают одноранговые узлы, и приглашения выдаются.
Но когда я нажимаю "Принять" на одноранговом устройстве, браузер продолжает показывать "Соединение" без конца. Я думал, что 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];
}
Заранее спасибо!
3 ответа
Спасибо комментаторам за прекрасные предложения, которые привели к тому, что я нашел свою ошибку. И вот оно:
Если вы реализуете MCSessionDelegate
метод session:didReceiveCertificate:fromPeer:certificateHandler
метод, он будет перехватывать попытку партнера подключиться к сеансу. Вы должны либо явно одобрить это соединение в этом методе, либо закомментировать его.
Детали и извлеченные уроки:
В дополнение к коду, который я показал, я сделал короткие реализации различных методов делегата. Один MCSessionDelegate
метод это один:
- (void) session:(MCSession *)session
didReceiveCertificate:(NSArray *)certificate
fromPeer:(MCPeerID *)peerID
certificateHandler:(void (^)(BOOL))certificateHandler
{
}
Продолжая совет @Big-O Claire выше, я начал наблюдать за всеми этими методами делегатов, Just In Case. И это сработало, когда партнер нажал кнопку "Принять" в интерфейсе AdvertiserAssistant.
Этот метод дает вам возможность решить, является ли одноранговый узел законным и не подключен (используя certificateHandler:
) если не хочешь. Apple говорит,
Ваше приложение должно проверить сертификат соседнего партнера, а затем решить, доверять ли этому сертификату. После этого определения ваше приложение должно вызвать предоставленный блок certificateHandler, передавая либо YES (чтобы доверять соседнему узлу), либо NO (чтобы отклонить его).
Кроме того, вы получите этот совет:
Важное замечание: Структура многопользовательского подключения не предпринимает никаких попыток проверить предоставленные одноранговым узлом удостоверения или сертификаты каким-либо образом. Если ваш делегат не реализует этот метод, все сертификаты принимаются автоматически.
Когда я прокомментировал этот метод, соединения прошли - и ЭТА проблема, по крайней мере, была решена.
У меня была та же проблема, и оказалось, что я использую один и тот же сеанс как для браузера, так и для рекламодателя. разделите сессии, но убедитесь, что 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];
}
Я не ушел MCBrowserViewController
при работе с новой платформой MC, но из слайда 51 презентации WWDC это выглядит как browserViewControllerDidFinish:
вызывается только тогда, когда пользователь нажимает "Готово". Таким образом, этот обратный вызов, вероятно, не в том, в чем проблема, если ваш партнер по-прежнему отображается как "Соединение...".
Мне интересно, если вы должны подключить своих коллег к сеансу вручную. Вы уже устанавливаете MCSession
делегат, так что я предполагаю, что вы реализуете session:peer:didChangeState
, Установите точку останова и следите за тем, когда MCSessionState
является MCSessionStateConnected
, Единственное, в чем я не уверен - это если вам нужно вручную обработать это на стороне рекламодателя, на стороне браузера или на обеих сторонах. Если бы вы могли выяснить, на каком этапе фреймворк перестает с ним работать, это было бы полезно.