MessageUI Framework

iOS 10 introduces a new concept called MessageUI Extensions: a way for you to share your app functionality with other apps, with to the OS itself.

LNMessageExtension

In this article, LN keyword is used which is shorthand for LetsNurture. By end of this tutorial, your message extension will look like this.

Screen Shot 2016-08-01 at 5.53.39 PM

Prerequisites

  • Xcode 8.0 beta
  • iOS 10

Create new Project

In Xcode select File and then Select New \ Project. When the Template picker appears Select iOS \ Application \ Message Application. Click Next.

Screen Shot 2016-07-28 at 5.45.30 PM

Set the product name to LNMessageExtension and Click Finish.

Screen Shot 2016-08-01 at 4.22.55 PM

Now you have default MessageViewController.swift file and MainInterface.storyboard.

Screen Shot 2016-08-01 at 4.23.29 PM

Screen Shot 2016-08-01 at 4.23.52 PM

 

How to run?

As this is an extension, it will be attached with another application. So we will run project in Message Application. To run the application, select available simulator which has inbuilt Message Application. Run the application and you will be prompted with app picker. Then Select Message Application and click Run.

Screen Shot 2016-08-01 at 6.25.11 PM

Xcode will open Message Application.

Screen Shot 2016-08-01 at 6.31.44 PM

Now to run LNMessageExtension click symbol below. And swipe right or left to find your extension.

Simulator Screen Shot 01-Aug-2016, 6.31.10 PM         Simulator Screen Shot 01-Aug-2016, 6.38.52 PM

 
As you can see it is very easy and interesting now you have open playground to play with. We can Edit this viewController as we want. Let us make one sticker app , Stickers of some Cuties and some Pokemon avatars.

male_kid_1 girl_kid_3 girl_kid_2 girl_kid_1 male_kid_2 male_kid_3 ironchu pikapool spikachu superka THORKA

 

Sticker App

First delete the Hello world UILabel from MessageViewController. Now Add another UIViewController  and make new swift file to connect with AddMessageVC.swift. And Design AddMessageVC as below. Add Sticker images in Assets.xcassets folder of MessageExtension not LNMessageExtension as there will be 2 Assets.xcassets do not get confused.

Screen Shot 2016-08-01 at 7.18.54 PM

 

There is one UICollectionView and two buttons for option.

 

Now in AddMessageVC.swift file add this code.

 

import UIKit

protocol AddmessgaeDelgate : class {
    func addmessgaedidsubmit(image: String , caption: String)
}
class AddMessageVC : UIViewController, UICollectionViewDelegate,UICollectionViewDataSource{
    weak var delegate : AddmessgaeDelgate!
    
    @IBOutlet var collectionAvatar: UICollectionView!
    @IBOutlet var btnPokemon: UIButton!
    @IBOutlet var btnCuties: UIView!
    
    var strFlag = "C"
    
    var arrayCuties : [String] = ["Asset 1","Asset 2","Asset 3","Asset 4","Asset 5","Asset 6"]
    var arrayPokemon : [String] = ["Batchu","captain-GO","flachu","hulk-go","ironchu","pikapool","spikachu","superka","THORKA","wolverachu"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        collectionAvatar.reloadData()
    }
    
    @IBAction func btnPokemonClick(_ sender: AnyObject) {
        strFlag = "P"
        collectionAvatar.reloadData()
    }
    @IBAction func btnCutiesClick(_ sender: AnyObject) {
        strFlag = "C"
        collectionAvatar.reloadData()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if strFlag == "C"
        {
            return arrayCuties.count;
        }
        else{
            return arrayPokemon.count;
        }
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        let cell = collectionAvatar.dequeueReusableCell(withReuseIdentifier: "AvatarCell",for: indexPath as IndexPath) as! AvatarCell
        if strFlag == "C"
        {
            cell.imgAvtar.image = UIImage(named: arrayCuties[indexPath.row])
        }
        else{
            cell.imgAvtar.image = UIImage(named: arrayPokemon[indexPath.row])
        }
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if strFlag == "C"
        {
            if (indexPath.row == 0)
            {
                let caption = "My Short brown hair! :)"
                //  let img = UIImage(named: )
                self.delegate.addmessgaedidsubmit(image: "Asset 1", caption: caption)
            }
            else if(indexPath.row == 1)
            {
                let caption = "I am a cute GIRl! :)"
                self.delegate.addmessgaedidsubmit(image: "Asset 2", caption: caption)
            }
            else if(indexPath.row == 2)
            {
                let caption = "Love my long orange Hair! ;)"
                self.delegate.addmessgaedidsubmit(image: "Asset 3", caption: caption)
            }
            else if(indexPath.row == 3)
            {
                let caption = "I am a cute BOy! :)"
                self.delegate.addmessgaedidsubmit(image: "Asset 4", caption: caption)
            }
            else if(indexPath.row == 4)
            {
                let caption = "Hows My New Hair Style! :)"
                self.delegate.addmessgaedidsubmit(image: "Asset 5", caption: caption)
            }
            else
            {
                let caption = "My new ROUnd Cute Specs! :)"
                self.delegate.addmessgaedidsubmit(image: "Asset 6", caption: caption)
            }
        }
        else{
            self.delegate.addmessgaedidsubmit(image: arrayPokemon[indexPath.row], caption: "")
        }
    }
}

 

Now  add below code in MessagesViewController.swift

 

import UIKit
import Messages
class AvatarCell: UICollectionViewCell
{
    @IBOutlet var imgAvtar: UIImageView!
}

class MessagesViewController: MSMessagesAppViewController , AddmessgaeDelgate{
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    func addmessgaedidsubmit(image: String, caption: String) {
        let componenets = NSURLComponents()
        let layout = MSMessageTemplateLayout()
        layout.caption = caption
        layout.image = UIImage(named: image)
        let message = MSMessage()
        message.url = componenets.url
        message.layout = layout
        self.activeConversation?.insert(message, localizedChangeDescription: "", completionHandler: { (error :NSError?) in
        })
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    private func presentviewController (for conversation:MSConversation , with presentationstyle: MSMessagesAppPresentationStyle)
    {
        var controller : UIViewController!
        
        if presentationstyle == .compact
        {
            controller = instansiateAddMessageCOntroller()
        }
        addChildViewController(controller)
        controller.view.frame = view.bounds
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(controller.view)
        controller.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        controller.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        controller.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        controller.didMove(toParentViewController: self)
    }
    private func instansiateAddMessageCOntroller() -> UIViewController{
        let controller = storyboard!.instantiateViewController(withIdentifier: "AddMessageVC") as! AddMessageVC
        controller.delegate = self
        return controller
    }
    
    // MARK: - Conversation Handling
    
    override func willBecomeActive(with conversation: MSConversation) {
        print(conversation.selectedMessage?.url)
        presentviewController(for: conversation, with: presentationStyle)
        // Called when the extension is about to move from the inactive to active state.
        // This will happen when the extension is about to present UI.
        
        // Use this method to configure the extension and restore previously stored state.
    }
    
    override func didResignActive(with conversation: MSConversation) {
        // Called when the extension is about to move from the active to inactive state.
        // This will happen when the user dissmises the extension, changes to a different
        // conversation or quits Messages.
        
        // Use this method to release shared resources, save user data, invalidate timers,
        // and store enough state information to restore your extension to its current state
        // in case it is terminated later.
    }
    
    override func didReceive(_ message: MSMessage, conversation: MSConversation) {
        // Called when a message arrives that was generated by another instance of this
        // extension on a remote device.
        
        // Use this method to trigger UI updates in response to the message.
    }
    
    override func didStartSending(_ message: MSMessage, conversation: MSConversation) {
        // Called when the user taps the send button.
    }
    
    override func didCancelSending(_ message: MSMessage, conversation: MSConversation) {
        // Called when the user deletes the message without sending it.
        
        // Use this to clean up state related to the deleted message.
    }
    
    override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
        // Called before the extension transitions to a new presentation style.
        // Use this method to prepare for the change in presentation style.
        self.presentviewController(for: activeConversation!, with: presentationStyle)
    }
    
    override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
        // Called after the extension transitions to a new presentation style.
        
        // Use this method to finalize any behaviors associated with the change in presentation style.
    }
    
}

That is it. Give Connections to controls in storyboard and you are done. Run the Application.

Simulator Screen Shot 01-Aug-2016, 7.44.24 PM  Simulator Screen Shot 01-Aug-2016, 7.46.56 PM

 

I hope this is enough details and you have learned about MessageUI Framework. You can refer https://www.youtube.com/watch?v=TkBUKHxjIcw

 

Want to work with us? We're hiring!