Question

How can i create a custom invitation which will display the discoveryInfo from the advertiser?

Here is the code from my advertiser:

// create Discovery Info
NSArray *objects=[[NSArray alloc] initWithObjects:@"datguy",@"28", nil];
NSArray *keys = [[NSArray alloc] initWithObjects:@"Name",@"Age", nil];
self.dictionaryInfo = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];

//  Setup Advertiser
self.advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:@"txt_msg_service" discoveryInfo:self.dictionaryInfo session:self.advertiseSession];
[self.advertiser start];
Was it helpful?

Solution

i think you got it backwards. IFAIK, the discoveryInfo of the MCAdvertiserAssistant is the information passed from the advertiser for the browsers. This information is passed to:

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info

which is a delegate method for the MCNearbyServiceBrowser class. And to this:

– browserViewController:shouldPresentNearbyPeer:withDiscoveryInfo:
Which is the delegate for the MCBrowserViewController class.

This information should be used to check if this advertiser should be displayed for your user.

If you are interested in intercepting an invitation attempt, you should consider using the MCNearbyServiceAdvertiser class instead of the assistant. This way you can delegate the didReceiveInvitationFromPeer method and add some custom logic to it:

// pedido para entrar na sala.
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID
       withContext:(NSData *)context
 invitationHandler:(void (^)(BOOL accept, MCSession *session))invitationHandler {
    // get the browser's info
    NSDictionary *peerInfo = (NSDictionary *) [NSKeyedUnarchiver unarchiveObjectWithData:context];

    //check if peer is valid for this room (add your custom logic in this method)
    if ([self isValidForThisRoom:peerInfo]) {
        //create an alert
        NSObject *clientName = [peerInfo valueForKey:@"playerName"];
        NSString *clientMessage = [[NSString alloc] initWithFormat:@"%@ wants to connect. Accept?", clientName];
        UIAlertView *alertView = [[UIAlertView alloc]
                initWithTitle:@"Accept Connection?"
                      message:clientMessage
                     delegate:self
            cancelButtonTitle:@"No"
            otherButtonTitles:@"Yes", nil];
        [alertView show];

        // copy the invitationHandler block to an array to use it later
        ArrayInvitationHandler = [NSArray arrayWithObject:[invitationHandler copy]];
    } else {
        // if the peer is not valid, decline the invitation
        invitationHandler(NO, _session);
    }
}

On the clickedButtonAtIndex delegate for the alertview, you can do something like this:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    //obtem a decisao do usuario
    BOOL accept = (buttonIndex != alertView.cancelButtonIndex) ? YES : NO;

    // obtem o invitationHandler que foi guardado do didReceiveInvitationFromPeer
    void (^invitationHandler)(BOOL, MCSession *) = [ArrayInvitationHandler objectAtIndex:0];

    // chama o invitationHandler passando a nossa session
    invitationHandler(accept, _session);
}

Two important things to notice is that:

  1. Your session object should be an instance variable, not local as i saw in some code samples. In my experience, i just created a static shared instance to store the session object. This is also a good plan if you want to pass the session from one screen to another.

  2. Notice that you should create an NSArray *ArrayInvitationHandler; variable to store the block code. I tried to do Block_copy but it had some conversion errors going on so someone here in stackoverflow decided to store in an array, which i think is elegant enough.

Anyway, i got it working using this setup. Hope it helps you :D

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top