MSMessageLiveLayout : Blank message

Hello,


My application already have an iMessage Extension since iOS10 that work perfectly.

I am trying to use MSMessageLiveLayout available in iOS11 but it doesn't work, the "Balloon" inserted in the conversation is blank.


There is my code :


- (void)composeMessageWithItem:(NSObject<MSMessageTemplateLayoutProtocol> *)item {

    MSConversation *conversation = self.activeConversation;
    MSMessage *message = [self messageTemplateLayoutWithItem:item
                                                     session:conversation.selectedMessage.session];

    [conversation insertMessage:message completionHandler:^(NSError *error) {

        NSLog(@"ERROR = %@", error);

    }];

}

- (MSMessage *)messageTemplateLayoutWithItem:(NSObject<MSMessageTemplateLayoutProtocol> *)item session:(MSSession *)session {

    MSMessageTemplateLayout *templateLayout = [MSMessageTemplateLayout new];
    templateLayout.image = item.image;
    templateLayout.caption = item.caption;
    templateLayout.subcaption = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];

    MSMessageLayout *layout = templateLayout;

    if (@available(iOS 11.0, *)) {
  
        // If i comment this line, everything is fine and the "Ballon" uses the iOS 10 template
        layout = [[MSMessageLiveLayout alloc] initWithAlternateLayout:templateLayout];
    }

    NSURLComponents *components = [NSURLComponents new];
    components.queryItems = item.queryItems;

    MSMessage *message = [[MSMessage alloc] initWithSession:(session != nil ? session : [MSSession new])];
    message.URL = components.URL;
    message.layout = layout;

    return message;

}


Is anyone succeeded in making MSMessage with MSMessageLiveLayout ?

If the answer is YES, how ?

Can you post your code please ?


Thank you.

Accepted Reply

I found the solution.


When you use MSMessageLiveLayout, do not set the url property of the MSMessage object. Right code below :


- (MSMessage *)messageTemplateLayoutWithItem:(NSObject<MSMessageTemplateLayoutProtocol> *)item session:(MSSession *)session {
  
    MSMessageTemplateLayout *templateLayout = [MSMessageTemplateLayout new];
    templateLayout.image = item.image;
    templateLayout.caption = item.caption;
    templateLayout.subcaption = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
  
    MSMessageLayout *layout = templateLayout;
  
    if (@available(iOS 11.0, *)) {
        layout = [[MSMessageLiveLayout alloc] initWithAlternateLayout:templateLayout];
      
    }
  
    MSMessage *message = [[MSMessage alloc] initWithSession:(session != nil ? session : [MSSession new])];
    message.layout = layout;
  
    return message;
  
}

Replies

Have you overrided contentSizeThatFits in your MSMessagesAppViewController?

Yes i did.


- (CGSize)contentSizeThatFits:(CGSize)size {
   
    return CGSizeMake(size.width, 215);
   
}

I found the solution.


When you use MSMessageLiveLayout, do not set the url property of the MSMessage object. Right code below :


- (MSMessage *)messageTemplateLayoutWithItem:(NSObject<MSMessageTemplateLayoutProtocol> *)item session:(MSSession *)session {
  
    MSMessageTemplateLayout *templateLayout = [MSMessageTemplateLayout new];
    templateLayout.image = item.image;
    templateLayout.caption = item.caption;
    templateLayout.subcaption = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
  
    MSMessageLayout *layout = templateLayout;
  
    if (@available(iOS 11.0, *)) {
        layout = [[MSMessageLiveLayout alloc] initWithAlternateLayout:templateLayout];
      
    }
  
    MSMessage *message = [[MSMessage alloc] initWithSession:(session != nil ? session : [MSSession new])];
    message.layout = layout;
  
    return message;
  
}

Is this documented anywhere? I have live layout balloons appear and also use a query url to pass some data (or access points to data) that shows in those balloons. But I'm also having undesireable behavior with live layout, such as the balloon does not show immediately after the updated message is sent, but it will display if the user quits and restarts Messages. I've tested not setting the url, but that doesn't change the behavior.


Is there a formal either/or connection between LiveLayout and the query url?


From https://developer.apple.com/documentation/messages/msmessage "Before using an MSMessage object, you must set both its url and layout properties."


Not saying it works or doesn't...just trying to understand it.

I'm curious if you can't set message.URL, how are you managing your message content? [MSMessageLiveLayout alternateLayout] lets you access the MSMessageTemplateLayout, from which I thought I could get the sent image or mediaURL. However, I am finding that the conversation.selectedMessage.layout is nil in didBecomeActiveWithConversation:(MSConversation *)conversation

This is frustrating because it is available in didReceiveMessage:(MSMessage *)message conversation:(MSConversation *)conversation. But, that is not called unless the extension is running when the message arrives.


As I understood it, the work around in iOS10 was to upload the media to your own server, and then pass the URL to it in message.URL, to the recipient could download. This is difficult to work with because the message might arrive before the upload has completed, and even if the upload is complete, you can't begin the download until the user begins interacting with the message. Yet, iMessage will happily transport the data if you provide a layout.mediaURL; it just won't let you access it on the receiving side. As near as I can figure.

The url is the accessible property. Can't access any parts of the layout. https://forums.developer.apple.com/thread/53174 makes this clear. I'm with you that the url is necessary for message content.


I have live layout working, and am using the url property. I was experiencing a case where the message bubble was animating to empty under certain situations, but a device upgrade to iOS 11.1 beta 4 seems to have fixed that. Can't swear that actually is the source of the problem, but that device no longer shows empty message bubble. Installing the iOS update on other devices now to see if same result. Maybe just coincidence, maybe cause-and-effect.

The curious thing is the originally layout is accessible within the didReceiveMessage callback. The user experience of being presented with a message, whose content is not actually available yet, is broken.