Messages apps allow people to collaborate by using your app. Learn how people can work together to accomplish a task within the conversation. Customize the appearance of the messages your app can send. Learn about how to manage your app state in one-to-one and group conversations to provide an engaging and collaborative experience.
Welcome to "iMessage Apps and Stickers, Part 2".
My name's Alex and with me today helping present is Stephen.
He's going to do the demos.
So, in the first part of this talk, Bhaskar
and Lily introduced stickers, sticker packs,
and simple iMessage apps focused
on providing sticker data to messages.
Today we're going to talk about interactive messages
and we're going to dive deeper into the iMessage apps
and the Messages framework.
So, what are interactive messages?
Well, you can see one here behind me highlighted
in the Messages transcript.
This is a special type of message bubble provided
by a Messages extension and you can see that's shown here
in the screenshot highlighted.
Messages extensions allow your users
to compose interactive messages and then they allow them
to insert them on the input field, as shown here.
They also allow a user to reply to an interactive message
by tapping one in the transcript
and in this point an extension will be launched full screen,
as shown here.
The user can interact with this extension to compose a reply.
Your extension can then insert this new content
into the messages and it will show here on the input field
and the user can send it.
So, now we're going to welcome Stephen to the stage
and he's going to show you our sample app running
in the simulator.
I'm going to show you a completed iMessage application
that I've written to demo all of the APIs that we're going
to learn in today's session.
If you look here in the simulator, you'll see the icon
from my iMessage app called Ice Cream.
When I tap this, my iMessage app is revealed here running
within the context of Messages.
All of the UI with this pink background is code--
is UI provided by my extension.
Now, my iMessage app is a collaborative ice cream
sticker-building application and here you see a history
of ice cream stickers that I've already built.
When I tap this Add button here, my iMessage app will expand
to take the full screen and I'll have this nice sticker-building
If I choose an ice cream cone, my iMessage app dismisses
and stages an interactive message
in the input field for the user to send.
Now, on iOS 10, we've added support for you to--
for you to develop and test your iMessage apps right
within the simulator.
If you go back to the conversation list here,
you'll see two ends of a simulated conversation.
Tapping the second one shows the simulated received message.
When I tap this, my iMessage app is launched with the next step
in the ice cream building process.
I can select my favorite ice cream, mint chip,
stage that message, and send it.
Now, if I go back to that first conversation or the first end
of the conversation and tap this message
and select the final part of the ice cream, my topping,
and send it, I now have a completed ice cream
that I've built.
In fact, now when I go back into my iMessage app,
you'll see that it appears here in my ice cream history
as a sticker that I can then apply anywhere I want to.
And that's a quick sample of what you can do
with interactive messages.
And now back to Alex.
That was just a great quick demo of some
of the features of iMessage apps.
So, let's talk about how we can accomplish this with our APIs.
I'm going to go through four things.
One of them-- so I'm going to give you an overview
of the API followed by number two, a little look
into the extension lifecycle.
Number three, we're going to talk about how
to compose a message using our APIs.
Number four, we're going to talk a little bit
about how the message is sent.
So, starting with the API overview.
We have our iMessage app running here,
shown in compact presentation mode and this is an extension.
Extensions have a principal class
and for iMessage apps this will be a subclass
of the MSMessagesAppViewController.
the MSMessagesAppViewController is a subclass
of UIViewController, so it's providing your extension's UI.
Above the extension, we have the conversation
and specifically the conversation transcript.
This is represented in our API by the MSConversation object.
And finally we have a message itself.
We have this bubble here in the transcript
and this is represented by the MSMessage class.
Also, you'll note in this slide we have another two classes
shown, the MSSession and MSMessageTemplateLayout.
These provide some control over how the message is sent
and how the message appears in the transcript.
So, let's move on and talk about iMessage extension lifecycle.
Here we have a timeline and when an extension is launched,
perhaps from the app drawer, we're going to launch a process.
Shortly afterwards, we'll call didBecomeActive
with conversation and we're going to pass
in a conversation object
that represents the conversation your app is running within.
And since this is a UIViewController subclass,
we'll also call will-- viewWillAppear and viewDidAppear
as your extension appears onscreen.
Now, what happens when your app remove--
is removed from the screen?
We're going to call this resigning active
and what happens is first you will receive viewWillDisappear,
viewDidDisappear calls on your principal class.
This is followed by a viewWill-- sorry--
this is followed
by a willResignActive call with conversation.
At this point, we're about to teardown the connection
between Messages and your extension.
So, this is the last time you get to do anything
with the conversation.
And then at some point later your process will be terminated
and this-- just to stress-- is because your process is built
on extensions and extensions are short-lived processes
and they're terminated aggressively.
So, let's see now that we have a process running and showing UI
within Messages, your user is going to interact with this UI
and build a message and let's see how we're going
to deal with that in our API.
Well, the first thing you're going
to do is create an MSMessage object and we're going
to set some properties on that object.
In this case, I'm setting an https URL
so the message is URL property and I'm encoding some detail
about the ice cream that we're building
in the query string of that URL.
The only platform that is able to generate iMessage--
these messages is iOS, but these messages will be sent
to macOS and to watchOS.
When they're delivered on macOS, they'll be shown
in full fidelity in the conversation transcript
and clicking on a message in the transcript will try
and get this URL and open it in your web browser.
So, if you provide an https URL here, then your website is able
to show-- should be able to show some representation
of the message for users on macOS.
Moving on, we have an accessibility label
This is used by screen readers when reading the transcript.
So, I'm setting this to a description
of the message bubble so that our users
who use screen readers get a great rich description
of the bubble as it is displayed in the transcript.
And finally I'm going to talk about-- we've got layout.
And I'm going to talk about this in a little bit more detail now.
The layout object is how we specify the appearance
of a message in the transcript.
Right now we only have one layout
and that's the MSMessageTemplateLayout.
We can set some properties on this
and this affects how the bubble is built.
So, right here we have an image property
and this takes a UI image and it provides content
for the area highlighted onscreen.
We also have a mediaFileURL property.
The mediaFileURL also provides content for the same area
as the image, but here you can provide content that's not
supported by UI image.
For instance, you could provide a URL to a local video file.
A short video would be then looped in the background
of the message bubble in the transcript.
Let's take a second to focus a little bit more
on these two properties.
We should note first that if the image
and the URL are both provided, then the image is going
to take precedence over the URL.
We had some recommended-- recommendations for the size
of the assets provided in these properties.
We're recommending that you provide your assets
at roughly 300 point by 300 point.
You can provide slightly larger assets
and slightly smaller assets and I really encourage you
to experiment with asset sizes here in order
to find what best suits your app and your needs.
All of these assets, as with stickers, are provided at 3x
and Messages will downsample and downscale these images
when they arrive on other devices as appropriate
for the screen resolution on that-- on the receiving device.
In the mediaFileURL, we support PNG, JPEG, GIF, and video.
When I say video, what I mean here is
that we support any videos that can be played
with our media player frameworks and I'd like to refer you
to the media player framework documentation
to find out more about this.
The other thing that we're going to do
with this media is we're going
to transcode the assets when they're sent.
This is in order to optimize them
for transfer over our networks.
And finally I'd like to encourage you
to avoid rendering text into this image.
As I said, these images are scaled down for display
on devices with 1x and 2x screens, yet we're asking you
to provide them at 3x.
If you were to render text into this image,
particularly small text, when these images are scaled down,
the text could be rendered illegible, but you'll notice
that we actually do show in this example some text drawn on top
of the image, so let's talk about how this is done
without degrading quality.
The layout has some additional properties over image--
the two that provide images-- and these are text properties.
They're transformatted with the message and drawn natively
on the receiving devices so we can draw the text
on the receiving devices as crisply and cleanly as possible.
We have here shown the image title
and this is text that's drawn on top of the image
in the lower left hand corner.
We have an image subtitle that's drawn again on top of the image,
right below the image title as shown.
And we have these caption properties
and these are drawn below the image in the caption bar.
That's this gray area onscreen.
So, we have caption, trailing caption, subcaption,
and trailing subcaption.
Now, if you look at the caption properties, it's also possible
to omit these altogether or set them all to nil.
If you do that, then you'll get a bubble
that doesn't have the caption bar at the bottom
and it'll look something more like this.
And one last thing to note on this slide.
We have an icon in the top left-hand corner of a bubble.
This icon is provided and drawn by Messages on top
of your content and this is always going
to be the iMessage app icon of the app that sent the message.
So, let's move on now and talk about how we send this message
that we've constructed.
To do that, we're going to need
to get an MSConversation instance.
You can get this from your principal class's
Once you have a conversation,
you can call the insert(message),
pass the message you constructed, and make sure
that you handle any errors that are returned.
Doing this will cause the message
to appear in the input field.
Of course, as mentioned in the first talk,
you can also send some other types of data.
We support sending text, attachments,
and of course stickers.
Once you've got your content on the input field,
the user is able to send the message
by tapping the blue Send button and I should note here
that there's no way for your extension
to actually automatically send a message
and we always want the user to have the final say
as to what gets sent to their friends.
So, now I'd like to hand you back over to Stephen
who is going to show you how we implement this
in our sample project.
Thanks again, Alex.
OK. I've taken the sample iMessage app
that I showed earlier in the session and stripped it
down to a very basic minimum for our starting point.
Here we still have our history of ice cream stickers
that have already been built, but you'll notice
that if I tap the Add button, nothing happens.
Here in Xcode, I have my MSMessagesAppViewController
I override the lifecycle method did become active
with conversation, call super,
and then call present child view controller
which is a helper method I've written
which will instantiate an ice cream history controller
and add it as a child view controller.
And that's all I have so far.
Now, what I'd like to do is
when I tap this Add button is start the
Now, this ice cream history view controller has a delegate
protocol and I have an extension on my messages view controller
which conforms to this delegate
by implementing the method historyViewController
This is where I'm going to trigger my functionality
and I'm going to also start
by adding a helper method called composeMessage for iceCream,
which will take an ice cream model object and will turn it
into an MSMessage for me to stage in my conversation.
To do so, I'm going to create an instance of URL components
and set the query items property of that URL components
to be a query items representation of my model.
Next thing I'm going to do is create an instance
of MSMessageTemplateLayout and set the image of that layout
to be a rendered version of my model.
I also want to set a caption for my message
and I'll declare my caption up here.
Now I'm ready to create my MSMessage object.
I'll do so by declaring an instance of MSMessage
and set the URL property
to be the URL representation of my components.
Then I'll set the layout and the accessibility label.
For brevity in the demo, I'm just going
to reuse my message caption as my accessibility label.
Now that I have my message,
I'm ready to stage it in the conversation.
I'll get a reference to my active conversation
and call conversation.insert
to insert the message so it is staged.
Now that I've written my composeMessage function,
here I'm ready to call it
from my historyViewController AddButtonTapped method.
And I'll start off by always adding
or passing a new ice cream model instance.
Now when I run this in the iOS simulator
and launch my iMessage application,
wait for that debugger to attach and tap the Plus (+) button.
My message is staged for the user to send.
Now, because I haven't actually selected any ice cream parts,
I just have a placeholder image for the ice cream
and you see my caption below the message.
Now, this is a great start, but I'd like to get closer
to that final demo that I showed you earlier.
When I tap that Plus (+) button, I want to go
into my sticker-building UI experience.
To do so, I need to introduce a new concept to you.
Here my iMessage app is presented
in a compact presentation style.
I can choose to have my iMessage app presented
in an expanded presentation style by requesting it.
Instead of calling composeMessage
for iceCream here, I'll call a method on my super class,
request presentation style with the expanded enum case.
This will trigger a lifecycle callback method called
willTransition to presentationStyle.
I'll call the super implementation
and then I'll call my helper method
to present the right child view controller
for this presentation style.
my presentChildViewController currently always presents my ice
cream history view controller and so I need
to change the logic to take into account the presentation style
so I present the correct view controller.
First, I'm going to add a parameter here so I know
which presentation style I'm dealing with.
Then I'm going to change this
to only present my history view controller when I'm
in the compact presentation style.
If I'm in the expanded case, I'm instead going
to declare a new instance of my ice cream model
and let my controller be an instance
of an ice cream builder view controller
to which I'll pass that ice cream model.
Now, lastly, before I add this as a child view controller,
I need to remove any previous child view controllers
to clean up my view hierarchy.
Now I need to update the call sites to my helper method.
Here I'm going to add that--
pass that pending presentation style and in the didBecomeActive
with conversation method,
I'm going to pass the current presentation style,
which I can get as a property on my parent view controller.
Should be right.
Lastly-- actually, let's see--
let's see what this looks like if I can get this to work.
And I tap that Plus (+) button.
My iMessage application goes to that expanded state
and I'm presenting that ice cream builder view-- experience.
However, you'll notice that when I tap Select nothing
Now, this is because my ice cream builder view controller
also has a delegate protocol and I have an extension
on my view controller here-- sorry to take you through that
so fast-- that implements this delegate protocol
by implementing the method iceCreamBuilderView controller
didSelect iceCreamPart for iceCream.
This is called whenever that Select button is tapped.
So, this is the right point for me to call
that helper method I wrote, compose message, and I'll pass
in the updated ice cream model from this method.
The other thing I'm going to do is call dismiss here
because my iMessage app is done preparing content and so I'd
like my iMessage app to dismiss
and display the staged message for the user.
Now when we launch this, tap the Plus (+) button
and select an ice cream cone.
I dismiss my iMessage app
and the correct interactive message is stage ready
for the user to send.
And that's a quick demo of what it looks
like to send an interactive message.
Now back to Alex.
Thank you, Stephen.
So, Stephen has introduced to you and shown you how
to use our APIs to insert content
into the conversation and send it.
Stephen also introduced presentation styles,
so we're going to have a quick look
at that in some more detail.
We have two presentation styles, compact and expanded.
Compact one is shown here and here we have expanded.
So, there's a couple of differences
between these two presentation styles.
In compact mode, you don't have access to the keyboard.
You also don't have access to horizontal scrolling,
swipe gesture recognizes.
This is because in the compact mode the user can swipe left
and right to switch between iMessage apps quickly.
However, you do have access to the input field,
so whenever insert message is called
in compact presentation style,
the message will be inserted right
into the input fields right away
and the user can see it immediately.
Subsequent calls to insert message will cause the current
message to be replaced with the new one,
so what you can do here is allow your user
to iteratively build a message, see it as it progresses
on the input field, and when they're happy
with it they can send it.
To contrast, in expanded presentation style we obviously
don't have access to the input field here,
but we do have access
to horizontal swipe gesture recognizes and scrolling
and you can use the keyboard.
The user can always transition your extension
between these two styles by tapping on the top chevron
from expanded to collapse to compact presentation style
and when in compact they can tap on the chevron at the bottom
of the screen to expand your app
into expanded presentation style.
So, when you're using iMessage apps,
you need to be very responsive to the area
in which your app is displayed.
Whenever these transitions happen, you're going
to get some callbacks on your principal class.
The willTransition to presentationStyle will be called
as the transition starts and at the end
when the transition is complete will call didTransition(to:
As Stephen showed, you can request presentation style
expanded or compact by calling the requestPresentationStyle
method on your principal class.
And again, as was shown in the demo, you can call dismiss
and this will dismiss your iMessage app
and show the keyboard.
So, let's move on and talk about how we reply to a message.
We have two cases here to cover.
One case when your extension is inactive and there's a bubble
in the transcript that the user taps and we're going
to look at that first.
We'll come back to the second case.
So, looking at our timeline again,
this should be very familiar.
The bubble is tapped by the user
and your process will be launched.
And now we go through exactly the same set of steps that we do
when your app is launched from the app drawer.
You'll get a didBecomeActive with conversation followed
by the viewWillAppear and viewDidAppear.
When this is done, you'll--
your app will be presented in expanded presentation style.
We always present apps in expanded presentation style
when the user taps a button to launch it-- sorry--
taps a bubble in the transcript to launch it.
Now, looking at our second case, the extension is already active.
In this case it's showing UI in the compact presentation style.
So, looking again at our timeline, in this case,
the bubble is tapped and the app is active.
So, we're not going to call willBecomeActive
Instead, you'll receive a call to willTransition
to presentationStyle expanded.
This is followed by a didSelect message and conversation.
This is called on your principal class and it lets you know
that the user tapped on a bubble in the transcript
and selected a message.
Then finally as the transition
to expanded presentation style completes you'll get the
didTransition to presentationStyle.
So, now at the end of both of these timelines,
your app is presenting the UI in the expanded presentation style
and you'll want to get that message that was tapped,
so this is done using the MSConversation's selectedMessage
property and you can get this
from the current active conversation
on your principal class.
You're going to want to show the selected message in your UI
and allow the user to compose a response.
Now I'd like you to hand you back over to Stephen
for one final demo showing you how
to implement reply in our sample app.
OK, so we left off
with a staged message we're sending here,
which I'll go ahead and send.
And now if I go back to the conversation list and go
to the other end of that conversation I have
that received message.
When I tap that message,
my iMessage app is correctly launched; however,
my ice cream building experience doesn't show the next step
in the ice cream building process.
I'm not ready to select ice cream scoops yet and this is
because every time
that I currently present this view controller,
I'm always passing in a new ice cream model object.
What I need to do is look at the selected message
on the conversation and use an ice cream model object
from that selected message if it exists.
So, I'll go back up here to where I'm instantiating
that ice cream builder controller and get a reference
to my active conversation .Then I will use a failable
initializer here that looks at the message on the conversation
and if that initializer fails then I know
that I don't have anything in progress and I'll just create
that new ice cream model, but if it does exist then I can pass
in the in progress ice cream.
The other thing I want to do is make sure
that I am passing the correct caption text depending
on the ice cream part that has been selected.
To do so, I'm going to need to pass a new parameter
into this method, which is the selectedIceCreamPart.
Now, this message caption here I'll change to a declaration
of the string type and then I'm going to switch
on the selectedIceCreamPart
to choose a correct message caption.
Oh, and I also need to update the call site to my method here
to pass in that new parameter.
Now when I launch my iMessage app, tap the Plus (+) button,
send that first message and then go back to the conversation list
and to the other end of the conversation
and now I'll tap the received message and you'll see
that my ice cream builder view controller is correctly set
up to pick an ice cream scoop.
Now I can select some mint chip, send it,
go back to the other end
of the conversation once more, and select a topping.
So, now you can see what it looks
like to send interactive messages back and forth
and accomplish a task collaboratively.
However, you'll see that in my conversation UI,
my partially built ice creams are starting
to pollute my conversation a little bit.
I don't really need to see the partially built ice creams,
I only really care about the completed ice cream.
What I'd like to do is collapse those previous messages
and maybe leave behind a succinct summary
of those messages.
To do so, I'm going to make use of a new object called MSSession
to group messages together.
Here when I'm composing my message,
I'm going to move my reference
to my active conversation a little bit so that
when I declare my session object I can look to see
if I have a session already on the selected message and use
that if it exists so that it will continue the same grouping.
Otherwise, I'll create a new MSSession object.
I'll then pass that session here
into my initializer for MSMessage.
Now, the other thing I want to do is provide a nice summary
of messages when they're collapsed.
Here I'm going to declare a method
or declare a variable called summary Text
and here I'll choose the right summaryText depending upon the
ice cream part that was chosen.
Now I could take that summaryText variable and set it
on my MSMessage object.
And that's it.
Oh, maybe I should actually assign it.
There we go.
Now when I launch my iMessage app and go about the process
of building an ice cream--
doesn't ice cream sound good right now?
I can pick my flavor of ice cream and you'll see
that that summary text has already been collapsed and shown
for me there when I send my message.
Now if I go-- sorry-- I'm going to go back to the first part
of the conversation, tap this message once more.
I think chocolate sounds like a good topping right now.
Now when I send that I have a completed ice cream message,
but I'm only showing the one--
the one image here and I have a nice summary text throughout my
Also, when I go into my Ice Cream app here,
you'll see my newly completed ice cream sticker ready for me
to use however I'd like.
And that's it.
We have a completed demo application.
Now, this was an example of how
to build an interactive sticker-building application,
but you could take this to do anything.
You can build-- you can integrate
with wonderful services
and build nice awesome collaborative games
and I can't wait to see what you build.
Now, back to Alex.
That was another awesome demo
and Stephen implemented the reply
and also introduced something new, the MSSession.
So, let's dive into the MSSession.
What we saw in the demo was a messy transcript containing lots
of half-completed ice creams and we saw how to use MSSession
to take that and turn it into something that looks a bit more
like this, which is a lot neater and less cluttered.
So, to implement this, we used an MSSession object.
We created an MSSession and then for our first message
that was part of the session, we passed that session
into its initializer and we have this session message.
We can set some summary text
and then we send it using the conversation's insert message,
as we've seen before.
When we're replying to a session message, we don't want
to create a new session; we need to reuse an existing one
and we can get the existing session
from the current conversation
so the activeConversation selectedMessage.
The selected message will have a second session property
if it's a session message.
Then we take that session, we pass it into the sessions--
the messages initializer, as we saw before.
We see here the summaryText is providing text
for the message summary in the conversation transcript.
You can now also omit this property or set it to nil
and if you do that then there will not be a summaryText entry
in the transcript, but your message will still partake
in the session behavior.
So, now we've covered the basics of the API and we've seen how
to build a very simple iMessage app
that sends interactive messages between your friends.
We're going to move on and talk about some
of the more advanced features of the API.
We'll start by looking at some more override methods
on your principal class.
We'll move on and talk about group conversations
and finally we'll discuss how to identify the sender
of a particular message.
First, when the user sends a message,
we realize that your app may wan to know that this has happened.
For instance, if you're a game and the user plays a move,
we need to know when to update our model to record that move
and that should really only happen
when the message is actually sent.
So, we have a didStartSendingMessage method
on the principal class and this is called
when the user taps the send button.
Now, this is important.
That message-- that does not mean
that the message has actually been sent or delivered.
All it means is the user has hit the Send button
and it communicates the intent to send this message.
We also have, similarly, a didCancelSending.
This happens when the user taps the cross
in the top right hand corner of the message bubble on the shelf.
didCancelSending is your opportunity to clean
up any resources that have been accumulated during the
composition of that message.
And lastly we have didRecieveMessage.
didRecieveMessage happens-- is called when your app is running
or active and a message has come in from one of the recipient--
one of the participants in the conversation.
And it's a-- this is useful, for example, if your app has--
if your user is editing a session message
and another message comes in on the same session,
it's an updated state and you need to update the UI
that represents this state.
So, let's move on and talk about group conversations.
iMessage apps are going to be used in group conversations,
so you're going to have to consider
that when you're building them.
We have here an example conversation
between three friends: Amber, Ben, and Chris.
Ben's getting ice cream for everyone and he sent
out a question to Amber and Chris.
Which topping do you-- would you like on your ice cream?
Chocolate sauce or sprinkles?
Amber is going to reply with chocolate sauce
and Chris here is going to reply with sprinkles.
Both users send these messages at exactly the same time.
Let's focus a little bit now on Ben and see what happens
on his device as these messages arrive.
First, Amber's reply is going to arrive on Ben's device
and this is followed very shortly afterwards
by the reply from Chris.
So, you note Amber's reply was turned into a summary message
and Chris's reply is shown
as the last bubble in this conversation.
This could just as easily have happened the other way around
and we should note that only the tapped message is available
to your iMessage app, so we don't really have access
to Amber's reply in our example.
How do we deal with this?
Well, right now we're recommending
that you store state in the cloud and this means
that the URL property of the MSMessage that's passed to
and from the participants in the conversation only needs to--
only needs to take a token that represents the session
and then you receive the current state of the session
when the user taps on a message.
And when a user sends a message,
you should push the current state
of the session up to the cloud.
Moving on, we're going to talk about sender identifiers.
Here we have a conversation
between Amber, Ben, and Chris again.
In this scenario, Amber has replied
with a preference for chocolate sauce.
Chris has not yet replied.
Focusing again on Ben's device, we have a message here
and we don't know who to attribute it to, but we can find
out some information about that.
Now, what we have here are some sender participant identifiers--
sorry, let me rephrase that.
What we have here are some participant identifiers.
Apple is very, very concerned about user privacy
and we really very highly value the privacy of our customers,
so we don't expose contact information
at all to iMessage apps.
Instead, we provide these participant identifiers.
On Ben's device, he has a local participant identifier
and this is a UUID that represents Ben on this device.
He also has two remote participant identifiers.
These represent the other participants
in the conversation.
In this case, we have two.
We have Amber and we have Chris.
Looking at the incoming message,
we see that the message has a sender identifier
and this will map to one
of the local participant identifiers in Ben's list.
Moving back to the big picture, looking at Amber
and Chris's device, the sending messages have sender identifiers
and these map to the local identifier on each device
that sent that message.
You can use these identifiers to get a handle on the number
of participants in a conversation.
You can attribute messages to a sender
so once you've received one message
with a particular sender identifier
and you receive a second with the same identifier,
you know they've come from the same user.
They can also be used in conjunction with a web service.
They can be used to help establish identity.
And one more thing.
You can use these identifiers or the string representation
of these identifiers prefixed with a dollar sign in any
of the text passed
to the MessageTemplateLayout's text properties.
You can also use-- similarly, you can use these identifiers
in the text passed to the Messages sumamaryText.
When Messages displays the UI for the bubbles with this type
of formatting in their text, it will replace the identifiers
with the contact name of the person
that their identifier maps to.
These identifiers are unique on each device.
If you noticed on the earlier slide, every device
for every person the identifier was different.
And they're scoped to the install of the iMessage app
and what I mean by this is
that the identifiers themselves will be stable over time,
but if the user removes your iMessage app
and then later reinstalls it,
you'll get a completely different set of identifiers
within the same conversation.
You can get the sender participant identifier
from an MSMessage using the senderParticipantIdentifier
property and you can get the local participant identifier via
conversation using the localParticipantIdentifier
And you can get the list of remote participant identifiers
from the remoteParticipantIdentifier
So, that wraps our more advanced topics on the API.
We're going to talk a little bit more about supported platforms.
Interactive messages will be delivered on these platforms:
watchOS 3, macOS Sierra, and iOS 10.
Of these platforms, only iOS 10 will actually generate messages.
On macOS Sierra, the user can click on a bubble
in the conversation transcript and the URL passed
to the Messages URL property will be opened with Safari.
That will only be if it's an https or http URL.
On watch, you can hand off interactive messages to a device
where you're able to compose a reply.
We also support some fallback for older platforms.
These messages will be delivered to watchOS 2, iOS 10--
iOS 9, and OS 10.11, but they'll be delivered
in a fallback format.
There's two separate messages.
The first one will be the image as provided
in the template layout.
The second one will be a URL as provided in the message.
Now, again note if this is an https URL, we'll send it.
If it's a data URL, we won't.
So, we only-- we'll only send the https or http URLs
in the fallback message.
So, that wraps up our talk.
In summary, we have-- this week,
we've introduced the Messages framework, iMessage apps.
In the first part of this talk, Bhaskar and Lily introduced us
to sticker packs and showed us how
to create simple iMessage apps that create sticker content.
Today, we've created iMessage apps
that send interactive content and we've talked
about how they work in group conversations
and a few other things.
Now I'm really excited to see what you guys go out
and make with this API.
I can't wait to see what you produce and that-- that's it.
For more information, you can check out our session's website
We have a related session.
If you haven't already seen "iMessage Apps and Stickers,
Part 1", then please go and watch it on the web.
And that wraps up our talk.
Thanks to Stephen for doing our demos.
Thanks to you guys for coming.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.