Swift Code to Send Message Not Working - ios

I am just learning to code and I am trying to create a simple code to send a message on IOS. I have made sure to import the MessageUI framework. When I run it on my simulator, it fails and shows THREAD 1 : SIGNAL SIGABRT. I apologize profusely if it's just a small mistake, as I often do such errors and don't wish to waste anyone's time. Here is my code:
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
#IBOutlet weak var messageLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func SendSMS(sender: AnyObject) {
let messageVC = MFMessageComposeViewController()
messageVC.recipients = ["5146276051"]
messageVC.body = messageLabel.text
messageVC.messageComposeDelegate = self
self.presentViewController(messageVC, animated: true, completion: nil)
}
func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) {
switch (result.rawValue) {
case MessageComposeResultCancelled.rawValue:
print("Message was cancelled")
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultFailed.rawValue:
print("Message has failed")
self.dismissViewControllerAnimated(true, completion: nil)
case MessageComposeResultSent.rawValue:
print("Message was sent")
self.dismissViewControllerAnimated(true, completion: nil)
default:
break
}
}
}
Thank you very much!

Hi try to use your code on physical device, it should work.
BTW in your code please add check whether device support sending messages:
#IBAction func SendSMS(sender: AnyObject) {
//Checking whether device support message sending
if (MFMessageComposeViewController.canSendText() == false) { return }
let messageVC = MFMessageComposeViewController()
messageVC.recipients = ["5146276051"]
messageVC.body = messageLabel.text
messageVC.messageComposeDelegate = self
self.presentViewController(messageVC, animated: true, completion: nil)
}
in that way you will avoid e.g. crashes on simulator.

Related

Refer a friend through SMS in swift 4

Hi want want to make a refer a friend through SMS I write the following code. If user is pick on that open the SMS with text but it don't cancel again user will unable go back to app.
if indexPath.item == 1
{
//SMS
if MFMessageComposeViewController.canSendText() {
let urlToShare = self.referalmodeldata[0].referralCodeOnly
controller1.body = "Hey I just gave an Awesome Assessment on App you can also try it. I scored , Try to beat my score \(String(describing: urlToShare))"
controller1.messageComposeDelegate = self as? MFMessageComposeViewControllerDelegate
self.present(controller1, animated: true, completion: nil)
}
}
You haven't implemented MFMessageComposeViewControllerDelegate correctly in your code.
First of all you need to confirm MFMessageComposeViewControllerDelegate with your UIViewController as shown below:
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
Next thing is you need add it's delegate method as shown below:
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.dismiss(animated: true, completion: nil)
}
Then you need to replace
controller1.messageComposeDelegate = self as? MFMessageComposeViewControllerDelegate
with
controller1.messageComposeDelegate = self
Demo code will be:
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
#IBAction func sendText(_ sender: Any) {
if (MFMessageComposeViewController.canSendText()) {
let controller = MFMessageComposeViewController()
controller.body = "Message Body"
controller.messageComposeDelegate = self
self.present(controller, animated: true, completion: nil)
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.dismiss(animated: true, completion: nil)
}
}

MessageComposeViewController only presents once

I'm using Xcode 8 to build an application for iPhone.My simple app has an button. When user tap on this button, messageComposeViewController is called and with phone number and message content filled.The message went through successfully when I clicked on Send button.The problem is MessageComposeViewController is showing only once.After the message sent, when I tapped on the button to call it, a black screen showed up instead of the message composer.My code is attached below. I appreciate any help.
import UIKit
import MessageUI
class ViewController: UIViewController, MFMessageComposeViewControllerDelegate {
let msg = MFMessageComposeViewController()
#IBOutlet weak var coordinate_label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func sendMessage(_ sender: AnyObject) {
self.msg.body = "Message Content"
self.msg.recipients = ["xxx-xxx-xxxx"]
self.msg.messageComposeDelegate = self
self.present(msg, animated: false, completion: nil)
}
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
switch result.rawValue {
case MessageComposeResult.cancelled.rawValue:
dismiss(animated: true, completion: nil)
case MessageComposeResult.failed.rawValue:
dismiss(animated: true, completion: nil)
case MessageComposeResult.sent.rawValue:
dismiss(animated: true, completion: nil)
default:
break;
}
}
}
Try this code
import Foundation
import MessageUI
let textMessageRecipients = ["1-800-867-5309"] // for pre-populating the recipients list (optional, depending on your needs)
class MessageComposer: NSObject, MFMessageComposeViewControllerDelegate {
// A wrapper function to indicate whether or not a text message can be sent from the user's device
func canSendText() -> Bool {
return MFMessageComposeViewController.canSendText()
}
// Configures and returns a MFMessageComposeViewController instance
func configuredMessageComposeViewController() -> MFMessageComposeViewController {
let messageComposeVC = MFMessageComposeViewController()
messageComposeVC.messageComposeDelegate = self // Make sure to set this property to self, so that the controller can be dismissed!
messageComposeVC.recipients = textMessageRecipients
messageComposeVC.body = "Hey friend - Just sending a text message in-app using Swift!"
return messageComposeVC
}
// MFMessageComposeViewControllerDelegate callback - dismisses the view controller when the user is finished with it
func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
}
Note, latest syntax 2017 ..
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
controller.dismiss(animated: true, completion: nil)
}
In Your viewController ..
import UIKit
class ViewController: UIViewController {
// Create a MessageComposer
let messageComposer = MessageComposer()
#IBAction func sendTextMessageButtonTapped(sender: UIButton) {
// Make sure the device can send text messages
if (messageComposer.canSendText()) {
// Obtain a configured MFMessageComposeViewController
let messageComposeVC = messageComposer.configuredMessageComposeViewController()
// Present the configured MFMessageComposeViewController instance
// Note that the dismissal of the VC will be handled by the messageComposer instance,
// since it implements the appropriate delegate call-back
presentViewController(messageComposeVC, animated: true, completion: nil)
} else {
// Let the user know if his/her device isn't able to send text messages
let errorAlert = UIAlertView(title: "Cannot Send Text Message", message: "Your device is not able to send text messages.", delegate: self, cancelButtonTitle: "OK")
errorAlert.show()
}
}
}

Reloading Views based on Tab Bar Interaction Xcode 7 Swift 2.0

I am tying to design a view controller that calls a method to load the embedded mail app on the iOS device as soon as the user taps the icon for that view, and every time it's tapped.
But after the mail client is either "Canceled", "Saved", "Sent" etc. The next time the user hits the Tab bar icon for that view controller the view is just a blank screen, it doesn't attempt to load the view again. I tried implementing a function call to loadView() or loadWillAppear() again but it ended up with an infinite loop where every time the mail client ended the client would load again instantly.
Perhaps I included the call a little early? I tried to even include some if statements to catch the program while it's running but it didn't seem to do anything at all. There's a couple places in here where I know it would be an infinite loop or what have you I just can't seem to get it to work. I was also unable to use:
override func viewWillAppear(animated: Bool)
Because the compiler complains about it and parsing boolean values is "Bad".
Anyways, here is the code from my ContactViewControllerTwo.swift
import Foundation
import UIKit
import MessageUI
class ContactViewControllerTwo: UIViewController, MFMailComposeViewControllerDelegate {
var mailControllerDidLoad = false
var mailControllerDismissed = false
override func viewDidLoad() {
viewWillAppear()
}
func viewWillAppear() {
if mailControllerDidLoad == false {
if MFMailComposeViewController.canSendMail() {
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setToRecipients(["123#123.com"])
presentViewController(composeVC, animated: true, completion: nil)
self.presentViewController(composeVC, animated: true, completion: nil)
}
else if mailControllerDidLoad == true && mailControllerDismissed == false{
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setToRecipients(["123#123.com"])
presentViewController(composeVC, animated: true, completion: nil)
self.presentViewController(composeVC, animated: true, completion: nil)
}
else {
print("Cannot send mail - Please try again")
// give feedback to the user
}
}
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParentViewController()
{
print("View controller")
}
else
{
print("New view controller.")
viewWillAppear()
print("Loaded again")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mailComposeController(controller: MFMailComposeViewController,
didFinishWithResult result: MFMailComposeResult, error: NSError?) {
mailControllerDidLoad = true
switch result.rawValue {
case MFMailComposeResultCancelled.rawValue:
print("Cancelled")
mailControllerDismissed = true
case MFMailComposeResultSaved.rawValue:
print("Saved")
mailControllerDismissed = true
case MFMailComposeResultSent.rawValue:
print("Sent")
mailControllerDismissed = true
case MFMailComposeResultFailed.rawValue:
print("Error: \(error?.localizedDescription)")
mailControllerDismissed = true
default:
mailControllerDismissed = true
break
}
controller.dismissViewControllerAnimated(true, completion: nil)
mailControllerDismissed = true
}
}

how to send a mail from my iOS application- SWIFT

I want to send a mail from my application. I am doing my first steps with SWIFT and i have stuck at a point. I want to press a button and open up the mail. Can you please tell me how to do the button connection? I think it should be an action but I don't know where to put it on the code
import UIKit
import MessageUI
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
func sendEmail() {
let mailVC = MFMailComposeViewController()
mailVC.mailComposeDelegate = self
mailVC.setToRecipients([])
mailVC.setSubject("Subject for email")
mailVC.setMessageBody("Email message string", isHTML: false)
presentViewController(mailVC, animated: true, completion: nil)
}
// MARK: - Email Delegate
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Import library first:
import MessageUI
set delegate like:
MFMailComposeViewControllerDelegate
Write pretty code:
#IBAction func buttonHandlerSendEmail(_ sender: Any) {
let mailComposeViewController = configureMailComposer()
if MFMailComposeViewController.canSendMail(){
self.present(mailComposeViewController, animated: true, completion: nil)
}else{
print("Can't send email")
}
}
func configureMailComposer() -> MFMailComposeViewController{
let mailComposeVC = MFMailComposeViewController()
mailComposeVC.mailComposeDelegate = self
mailComposeVC.setToRecipients([self.textFieldTo.text!])
mailComposeVC.setSubject(self.textFieldSubject.text!)
mailComposeVC.setMessageBody(self.textViewBody.text!, isHTML: false)
return mailComposeVC
}
Also write delegate method like:
//MARK: - MFMail compose method
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
100% working and tested
change sendEmail like this:
#IBAction func sendEmail(sender: AnyObject) {
let mailVC = MFMailComposeViewController()
mailVC.mailComposeDelegate = self
mailVC.setToRecipients([])
mailVC.setSubject("Subject for email")
mailVC.setMessageBody("Email message string", isHTML: false)
presentViewController(mailVC, animated: true, completion: nil)
}
and connect in Interface builder your button to this action
Swift 3
let composer = MFMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
composer.mailComposeDelegate = self
composer.setToRecipients(["Email1", "Email2"])
composer.setSubject("Test Mail")
composer.setMessageBody("Text Body", isHTML: false)
present(composer, animated: true, completion: nil)
}
Delegate method
class SendMailViewController: MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
dismiss(animated: true, completion: nil)
}
}
To send mail, generally MFMailComposer is used. It can be tested on device as it doesn't work on iOS simulator.
For testing whether mail service is available or not, use below function,
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
return
}
and to send mail, use below code in your function or action of button.
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
// Configure the fields of the interface.
composeVC.setToRecipients(["email_address#example.com"])
composeVC.setSubject("Hello World!")
composeVC.setMessageBody("Hello from iOS!", isHTML: false)
// Present the view controller modally.
self.presentViewController(composeVC, animated: true, completion: nil)
There is delegate method on completion of sending mail which can be defined as below shown,
func mailComposeController(controller: MFMailComposeViewController,
didFinishWithResult result: MFMailComposeResult, error: NSError?) {
// Check the result or perform other tasks.
// Dismiss the mail compose view controller.
controller.dismissViewControllerAnimated(true, completion: nil)
}
to Anton Platonov add: import MessageUI at the begging of your source file, and when you declaring class for your view controller add protocol: class FirstVC: UIViewController, MFMailComposeViewControllerDelegate{

Sending SMS in iOS with Swift

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.
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
}
}
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
}
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)
}
}
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;
}
}
UI will look like:
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;
}
}

Resources