First of all, I'm really surprised that this is not a duplicate, because there are TONS of stackoverflow questions that solve this in Objective-C, but I have yet to see a good answer that used Swift.
What I'm looking for is a code snippet in Swift that sends an arbitrary string as a the body of a text message to given phone number. Essentially, I'd like something like this from Apple's official documentation, but in Swift instead of Objective-C.
I imagine this isn't too difficult, as it can be done in just a couple of lines of code in Android.
EDIT: What I'm looking for is 5-20 lines of Swift code, I do not agree that this is too broad. In Java (for Android), the solution looks like this:
package com.company.appname;
import android.app.Activity;
import android.telephony.SmsManager;
public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); public static final mPhoneNumber = "1111111111"; public static final mMessage = "hello phone"; SmsManager.getDefault().sendTextMessage(mPhoneNumber, null, mMessage, null, null); }
}Now this is the android solution, and it's only 11 lines. Java tends to be much more verbose than Swift, so I doubt what I'm asking is "too broad", it is more likely that I don't know how to use the Objective-C MessageComposer object, because the documentation that I linked to above is unclear with regard to usage in Swift.
97 Answers
Not sure if you really got the answer. I was in a similar hunt and came across this solution and got it to work.
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate { @IBOutlet weak var phoneNumber: UITextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func sendText(sender: UIButton) { if (MFMessageComposeViewController.canSendText()) { let controller = MFMessageComposeViewController() controller.body = "Message Body" controller.recipients = [phoneNumber.text] controller.messageComposeDelegate = self self.presentViewController(controller, animated: true, completion: nil) } } func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) { //... handle sms screen actions self.dismissViewControllerAnimated(true, completion: nil) } override func viewWillDisappear(animated: Bool) { self.navigationController?.navigationBarHidden = false }
} 5 Swift 3.0 Solution:
func sendSMSText(phoneNumber: String) { if (MFMessageComposeViewController.canSendText()) { let controller = MFMessageComposeViewController() controller.body = "" controller.recipients = [phoneNumber] controller.messageComposeDelegate = self self.present(controller, animated: true, completion: nil) } } func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { //... handle sms screen actions self.dismiss(animated: true, completion: nil) } override func viewWillDisappear(_ animated: Bool) { self.navigationController?.isNavigationBarHidden = false } 0 For sending iMessage in Swift 5 I use following code
Just MessageUI package and implement MFMessageComposeViewControllerDelegate
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate { override func viewDidLoad() { super.viewDidLoad() } @IBAction func sendNewIMessage(_ sender: Any) { let messageVC = MFMessageComposeViewController() messageVC.body = "Enter a message details here"; messageVC.recipients = ["recipients_number_here"] messageVC.messageComposeDelegate = self self.present(messageVC, animated: true, completion: nil) } func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { switch (result) { case .cancelled: print("Message was cancelled") case .failed: print("Message failed") case .sent: print("Message was sent") default: return } dismiss(animated: true, completion: nil) }
} 1 Simpler solution may be opening html link:
let mPhoneNumber = "1111111111";
let mMessage = "hello%20phone";
if let url = URL(string: "sms://" + mPhoneNumber + "&body="+mMessage) { UIApplication.shared.open(url)
}Make sure you replaced spaces with "%20"
Swift 3, 4, 5
@IBAction func sendSmsClick(_ sender: AnyObject) { guard MFMessageComposeViewController.canSendText() else { return } let messageVC = MFMessageComposeViewController() messageVC.body = "Enter a message"; messageVC.recipients = ["Enter tel-nr"] messageVC.messageComposeDelegate = self; self.present(messageVC, animated: false, completion: nil) } func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { switch (result.rawValue) { case MessageComposeResult.cancelled.rawValue: print("Message was cancelled") self.dismiss(animated: true, completion: nil) case MessageComposeResult.failed.rawValue: print("Message failed") self.dismiss(animated: true, completion: nil) case MessageComposeResult.sent.rawValue: print("Message was sent") self.dismiss(animated: true, completion: nil) default: break; } } If you do not want to depend on an UIViewController, follows a Swift 3.0 solution:
import UIKit
import MessageUI
class ECMMessageComposerBuilder: NSObject { private dynamic var customWindow: UIWindow? private var body: String? private var phoneNumber: String? fileprivate var messageController: MFMessageComposeViewController? var canCompose: Bool { return MFMessageComposeViewController.canSendText() } func body(_ body: String?) -> ECMMessageComposerBuilder { self.body = body return self } func phoneNumber(_ phone: String?) -> ECMMessageComposerBuilder { self.phoneNumber = phone return self } func build() -> UIViewController? { guard canCompose else { return nil } messageController = MFMessageComposeViewController() messageController?.body = body if let phone = phoneNumber { messageController?.recipients = [phone] } messageController?.messageComposeDelegate = self return messageController } func show() { customWindow = UIWindow(frame: UIScreen.main.bounds) customWindow?.rootViewController = MNViewController() // Move it to the top let topWindow = UIApplication.shared.windows.last customWindow?.windowLevel = (topWindow?.windowLevel ?? 0) + 1 // and present it customWindow?.makeKeyAndVisible() if let messageController = build() { customWindow?.rootViewController?.present(messageController, animated: true, completion: nil) } } func hide(animated: Bool = true) { messageController?.dismiss(animated: animated, completion: nil) messageController = nil customWindow?.isHidden = true customWindow = nil }
}
extension ECMMessageComposerBuilder: MFMessageComposeViewControllerDelegate { func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { controller.dismiss(animated: true, completion: nil) hide() }
}You call the composer this way:
let phoneNumber = "987654321"
let composer = MNMessageComposerBuilder()
composer.phoneNumber(phoneNumber).show()or using a lazy var
let phoneNumber = "987654321"
private lazy var messageComposer: MNMessageComposerBuilder = { let composer = MNMessageComposerBuilder() return composer
}()
messageComposer.phoneNumber(phoneNumber).show() @IBAction func sendMessageBtnClicked(sender: AnyObject) { var messageVC = MFMessageComposeViewController() messageVC.body = "Enter a message"; messageVC.recipients = ["Enter tel-nr"] messageVC.messageComposeDelegate = self; self.presentViewController(messageVC, animated: false, completion: nil)
}
func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) { switch (result.value) { case MessageComposeResultCancelled.value: println("Message was cancelled") self.dismissViewControllerAnimated(true, completion: nil) case MessageComposeResultFailed.value: println("Message failed") self.dismissViewControllerAnimated(true, completion: nil) case MessageComposeResultSent.value: println("Message was sent") self.dismissViewControllerAnimated(true, completion: nil) default: break; }
} 1