How To Save Custom Info in MSMessage?

In iMessage Extensions for iOS10, when the user taps on the interactive message bubble:


How can you save custom information in the sent message so, when tapped, the extension is able to get that custom information and recognize the type of the tapped message?

Thanks!

Accepted Reply

I just figured it out by looking at Apple's Ice Cream Sample Code.


Solution


When creating the MSMessage you're going to send, use a NSURLComponents object to save the custom information in its QueryItems property.


Example:


MSMessage* message;
NSURLComponents* urlComponents;


// init
message = [[MSMessage alloc] init];
urlComponents = [NSURLComponents componentsWithURL:[NSURL URLWithString:@"http://yourwebsite.com"]];


// Saving custom info as Query Items
[urlComponents setQueryItems:@[[NSURLQueryItem queryItemWithName:@"messageType" value:@"1"],
                               [NSURLQueryItem queryItemWithName:@"username"    value:@"Jorge"],
                               [NSURLQueryItem queryItemWithName:@"userId"      value:@"99999"],
                               [NSURLQueryItem queryItemWithName:@"userPhoto"   value:@"http://yourwebsite.com/99999.jpg"]];


// Saving URL into message
[message setURL:[urlComponents URL]];


Final URL:

After doing something like in the example above, the final URL added to the MSMessage would end up being:

/message/https:/ NSURLComponents* urlComponents; / message = [[MSMessage alloc] init]; urlComponents = [NSURLComponents componentsWithURL:[NSURL URLWithString:@http://yourwebsite.com?messageType=1&username=Jorge&userId=99999&userPhoto=http://yourwebsite.com/9999.jpg

But these extra query items in the URL will be ignored. I mean, if your website is not intended to handle these query items, it will just ignore them when the user taps on that message bubble and opens the URL at the browser from a device with an iOS version less than 10 (iOS9, iOS8, ...).


The only drawback I see here is the exposure of the custom info to the user (when opening the URL). Maybe Apple should create a userInfo property in MSMessage.


Receiving Message

And this is how you would extract the info from the received message:



MSMessage* message; 
NSString* messageType, *username, *userId, *userPhoto;

//  init
message = [self.activeConversation selectedMessage]; 

if (message) 
{ 
     NSURLComponents *urlComponents;
     NSArray* queryItems; 

     // init
     urlComponents = [NSURLComponents componentsWithURL:[message URL] resolvingAgainstBaseURL:NO];
     queryItems = [urlComponents queryItems];

     for (NSURLQueryItem* item in queryItems)
     {
           if ([[item name] isEqualToString:@"messageType"])
                messageType = [item value];
           else if ([[item name] isEqualToString:@"username"])
                username = [item value]; 
           else if ([[item name] isEqualToString:@"userId"]) 
               userId = [item value];
           else if ([[item name] isEqualToString:@"userPhoto"])
                userPhoto = [item value];
           } 
     }     
       
}

Replies

I just figured it out by looking at Apple's Ice Cream Sample Code.


Solution


When creating the MSMessage you're going to send, use a NSURLComponents object to save the custom information in its QueryItems property.


Example:


MSMessage* message;
NSURLComponents* urlComponents;


// init
message = [[MSMessage alloc] init];
urlComponents = [NSURLComponents componentsWithURL:[NSURL URLWithString:@"http://yourwebsite.com"]];


// Saving custom info as Query Items
[urlComponents setQueryItems:@[[NSURLQueryItem queryItemWithName:@"messageType" value:@"1"],
                               [NSURLQueryItem queryItemWithName:@"username"    value:@"Jorge"],
                               [NSURLQueryItem queryItemWithName:@"userId"      value:@"99999"],
                               [NSURLQueryItem queryItemWithName:@"userPhoto"   value:@"http://yourwebsite.com/99999.jpg"]];


// Saving URL into message
[message setURL:[urlComponents URL]];


Final URL:

After doing something like in the example above, the final URL added to the MSMessage would end up being:

/message/https:/ NSURLComponents* urlComponents; / message = [[MSMessage alloc] init]; urlComponents = [NSURLComponents componentsWithURL:[NSURL URLWithString:@http://yourwebsite.com?messageType=1&username=Jorge&userId=99999&userPhoto=http://yourwebsite.com/9999.jpg

But these extra query items in the URL will be ignored. I mean, if your website is not intended to handle these query items, it will just ignore them when the user taps on that message bubble and opens the URL at the browser from a device with an iOS version less than 10 (iOS9, iOS8, ...).


The only drawback I see here is the exposure of the custom info to the user (when opening the URL). Maybe Apple should create a userInfo property in MSMessage.


Receiving Message

And this is how you would extract the info from the received message:



MSMessage* message; 
NSString* messageType, *username, *userId, *userPhoto;

//  init
message = [self.activeConversation selectedMessage]; 

if (message) 
{ 
     NSURLComponents *urlComponents;
     NSArray* queryItems; 

     // init
     urlComponents = [NSURLComponents componentsWithURL:[message URL] resolvingAgainstBaseURL:NO];
     queryItems = [urlComponents queryItems];

     for (NSURLQueryItem* item in queryItems)
     {
           if ([[item name] isEqualToString:@"messageType"])
                messageType = [item value];
           else if ([[item name] isEqualToString:@"username"])
                username = [item value]; 
           else if ([[item name] isEqualToString:@"userId"]) 
               userId = [item value];
           else if ([[item name] isEqualToString:@"userPhoto"])
                userPhoto = [item value];
           } 
     }     
       
}