How To Save Custom Info in MSMessage?
Asked Answered
P

3

6

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 to respond accordingly?

Thanks!

Pell answered 24/8, 2016 at 16:39 Comment(0)
P
4

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"] resolvingAgainstBaseURL:NO];

// Saving Custom Information 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/9999.jpg"]]];

// Setting message's URL
[message setURL:[urlComponents URL]];

Final URL:

The final URL added to the MSMessage would end up being:

http://yourwebsite.com?messageType=1&username=Jorge&userId=99999&userPhoto=http://yourwebsite.com/99999.jpg

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;  

    // Extracting message URL's coponents. With this URL we'll able to figure out the type of the message.
    urlComponents = [NSURLComponents componentsWithURL:[message URL]
                           resolvingAgainstBaseURL:NO];
    queryItems    = [urlComponents queryItems];

    // Extracting info from the query items.
    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];
    }
}
Pell answered 24/8, 2016 at 17:1 Comment(0)
T
6

Since this is an iOS 10 question, I hope the following answer in Swift will be helpful to others. (Original answer by @jmoukel, just converted to Swift by me).

let message = MSMessage()
guard let url = NSURL(string: "http://yourwebsite.com") else { return }
guard let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) else { return }
urlComponents.setQueryItems([
    "messageType": "1",
    "username":"Jorge",
    "userId":"99999",
    "userPhoto":"http://yourwebsite.com/9999.jpg"
])
message.setURL(urlComponents.URL!)
Tower answered 24/8, 2016 at 18:35 Comment(1)
getting this error whenever i make NSURLCmponents Ambiguous use of 'init(URL:resolvingAgainstBaseURL:)'Rahmann
P
4

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"] resolvingAgainstBaseURL:NO];

// Saving Custom Information 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/9999.jpg"]]];

// Setting message's URL
[message setURL:[urlComponents URL]];

Final URL:

The final URL added to the MSMessage would end up being:

http://yourwebsite.com?messageType=1&username=Jorge&userId=99999&userPhoto=http://yourwebsite.com/99999.jpg

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;  

    // Extracting message URL's coponents. With this URL we'll able to figure out the type of the message.
    urlComponents = [NSURLComponents componentsWithURL:[message URL]
                           resolvingAgainstBaseURL:NO];
    queryItems    = [urlComponents queryItems];

    // Extracting info from the query items.
    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];
    }
}
Pell answered 24/8, 2016 at 17:1 Comment(0)
J
0

MSMessage's url property is where you can store your custom data.

You can also use iMessageDataKit library. It makes setting and getting data really easy like:

let message: MSMessage = MSMessage()

message.md.set(value: 7, forKey: "user_id")
message.md.set(value: "john", forKey: "username")
message.md.set(values: ["joy", "smile"], forKey: "tags")

print(message.md.integer(forKey: "user_id")!)
print(message.md.string(forKey: "username")!)
print(message.md.values(forKey: "tags")!)

It also supports storing arrays.

(Disclaimer: I'm the author of iMessageDataKit)

Jowett answered 14/10, 2017 at 17:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.