In Swift I would do this to display a precomposed message
let composeVC = MFMessageComposeViewController()
composeVC.messageComposeDelegate = self
composeVC.recipients = ["9999999999"]
composeVC.body = "Text Message"
if MFMessageComposeViewController.canSendText() {
    self.present(composeVC, animated: true, completion: nil)
}
In SwiftUI this throws the error
Cannot assign value of type 'ContentView' to type 'MFMessageComposeViewControllerDelegate?'
and
Value of type 'ContentView' has no member 'present'
                You need to present over Windows rootview .Use these extension
import SwiftUI
import MessageUI
/// Main View
struct ContentView: View {
    private let mailComposeDelegate = MailComposerDelegate()
    private let messageComposeDelegate = MessageComposerDelegate()
    var body: some View {
        VStack {
            Spacer()
            Button(action: {
                self.presentMailCompose()
            }) {
                Text("email")
            }
            Spacer()
           Button(action: {
               self.presentMessageCompose()
           }) {
               Text("Message")
           }
            Spacer()
        }
    }
}
// MARK: The email extension
extension ContentView {
    private class MailComposerDelegate: NSObject, MFMailComposeViewControllerDelegate {
        func mailComposeController(_ controller: MFMailComposeViewController,
                                   didFinishWith result: MFMailComposeResult,
                                   error: Error?) {
            controller.dismiss(animated: true)
        }
    }
    /// Present an mail compose view controller modally in UIKit environment
    private func presentMailCompose() {
        guard MFMailComposeViewController.canSendMail() else {
            return
        }
        let vc = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
        let composeVC = MFMailComposeViewController()
        composeVC.mailComposeDelegate = mailComposeDelegate
        vc?.present(composeVC, animated: true)
    }
}
// MARK: The message extension
extension ContentView {
    private class MessageComposerDelegate: NSObject, MFMessageComposeViewControllerDelegate {
        func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
            // Customize here
            controller.dismiss(animated: true)
        }
    }
    /// Present an message compose view controller modally in UIKit environment
    private func presentMessageCompose() {
        guard MFMessageComposeViewController.canSendText() else {
            return
        }
        let vc = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
        let composeVC = MFMessageComposeViewController()
        composeVC.messageComposeDelegate = messageComposeDelegate
        vc?.present(composeVC, animated: true)
    }
}

inspiration and credits
The best way to present this view controller (or most any UIViewController) from SwiftUI is by making a struct using the UIViewControllerRepresentable protocol, then show it using a sheet() call in your view builder.
// MessageComposeView.swift
import MessageUI
import SwiftUI
struct MessageComposeView: UIViewControllerRepresentable {
    typealias Completion = (_ messageSent: Bool) -> Void
    static var canSendText: Bool { MFMessageComposeViewController.canSendText() }
        
    let recipients: [String]?
    let body: String?
    let completion: Completion?
    
    func makeUIViewController(context: Context) -> UIViewController {
        guard Self.canSendText else {
            let errorView = MessagesUnavailableView()
            return UIHostingController(rootView: errorView)
        }
        
        let controller = MFMessageComposeViewController()
        controller.messageComposeDelegate = context.coordinator
        controller.recipients = recipients
        controller.body = body
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(completion: self.completion)
    }
    
    class Coordinator: NSObject, MFMessageComposeViewControllerDelegate {
        private let completion: Completion?
        public init(completion: Completion?) {
            self.completion = completion
        }
        
        public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
            controller.dismiss(animated: true, completion: nil)
            completion?(result == .sent)
        }
    }
}
struct MessagesUnavailableView: View {
    var body: some View {
        VStack {
            Image(systemName: "xmark.octagon")
                .font(.system(size: 64))
                .foregroundColor(.red)
            Text("Messages is unavailable")
                .font(.system(size: 24))
        }
    }
}
Once you have that defined, you can use it like this
struct MyView: View {
    @State private var isShowingMessages = false
    var body: some View {
        Button("Show Messages") {
            self.isShowingMessages = true
        }
        .sheet(isPresented: self.$isShowingMessages) {
            MessageComposeView(recipients: ["recipients go here"], body: "Message goes here") { messageSent in
                print("MessageComposeView with message sent? \(messageSent)")
            }
        }
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With