Search code examples
iosswiftswift3ios-messages-extension

iOS 10 messages extension - implementing didRecieve() and selectedMessage in Simulator


I am attempting to implement didRecieve() to trigger a storyboard segue inside of a iOS 10 extension. Using the storyboard, I can trigger a segue after creating a message using the following code:

    @IBAction func createThing(_ sender: AnyObject) {
    self.createMessage()
}

func composeMessage(customMessage: String, caption: String) -> MSMessage {
    var components = URLComponents()

    // create a query item from our custom message
    let item = URLQueryItem(name: "New Thing", value: customMessage)

    // put it into an array of query items
    var items = [URLQueryItem]()
    items.append(item)
    components.queryItems = items

    // tell messages to use the default message template layout
    let layout = MSMessageTemplateLayout()
    layout.caption = caption

    // create a message and tell it the content and layout
    let message = MSMessage()
    message.url = components.url!
    message.layout = layout

    // return it for sending
    return message
}

override func didReceive(_ message: MSMessage, conversation: MSConversation) {

    print("message recieved!!")
    self.pollRecieved = true

    guard let messageURL = message.url else { return }
    guard let urlComponents = NSURLComponents(url: messageURL, resolvingAgainstBaseURL: false), let queryItems = urlComponents.queryItems else { return }

    print("URL Components", urlComponents)
    print("queryItems", queryItems)

    for item in queryItems {
        print("Received \(item.name) with value \(item.value)")
    }

    print("attempting segue!")
    self.performSegue(withIdentifier: "showPollSegue", sender: self)
}

func createMessage() {
    let message = composeMessage(customMessage: "This is really important.", caption: "User-facing caption here")
    self.activeConversation?.insert(message)
    print("message here!!", message)
}

// segue override
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if(segue.identifier == "showThingSegue") {
        let vc = segue.destination as! MessagesViewController
        vc.messageID = "1234567"
    }
}

This works great. I can send the message using i message after I create, and it is recieved by the IPhone simulator triggering a segue for the person sending the message.

The trouble comes in when I want to select the message in the other persons thread. Apple includes two interconnected message threads in the simulator for testing of sending and receiving messages between users with your extension.

When I select the message in the received thread, The segue is not triggered. It just loads a fresh copy of the root view controller.

The behavior I want is to grab the received information for a particular message instance, and trigger a segue using this data. Apple provides the following instance property to achieve this.

Refer to selectedMessage in API docs here: https://developer.apple.com/reference/messages/msconversation/1648186-selectedmessage

The question is how is this instance property implemented? Is it implemented in the onViewDidLoad() of the root view controller for your message extension? Apple's docs are pretty vague on how to actually implement the instance property to scoop the received message data from the selected message on the received end of your message extension. Has anyone implemented this?

THANKS!!


Solution

  • Once the receiver selects the message, willBecomeActive is called and gives you the MSConversation, which holds the selectedMessage:

    override func willBecomeActive(with conversation: MSConversation) {
        super.willBecomeActive(with: conversation)
        let message = conversation.selectedMessage
        ...
    }
    

    See: Helpful Apple sample