Envío de SMS en iOS con Swift


78

En primer lugar, estoy realmente sorprendido de que esto no sea un duplicado, porque hay TONELADAS de preguntas de desbordamiento de pila que resuelven esto en Objective-C, pero aún no he visto una buena respuesta que use Swift.

Lo que estoy buscando es un fragmento de código en Swift que envíe una cadena arbitraria como el cuerpo de un mensaje de texto a un número de teléfono dado. Esencialmente, me gustaría algo como esto de la documentación oficial de Apple, pero en Swift en lugar de Objective-C.

Me imagino que esto no es demasiado difícil, ya que se puede hacer con solo un par de líneas de código en Android.

EDITAR: Lo que estoy buscando son 5-20 líneas de código Swift, no estoy de acuerdo en que esto sea demasiado amplio. En Java (para Android), la solución se ve así:

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);
     }
}

Ahora bien, esta es la solución de Android, y solo tiene 11 líneas. Java tiende a ser mucho más detallado que Swift, así que dudo que lo que estoy preguntando sea "demasiado amplio", es más probable que no sepa cómo usar el objeto Objective-C MessageComposer, porque la documentación que vinculé lo anterior no está claro con respecto al uso en Swift.


2
He editado la publicación y creo que la pregunta que pretendo hacer no es demasiado amplia. Por favor, reconsidere el cierre de esta pregunta, o ayúdeme pidiendo detalles aclaratorios que omito y que hacen que el alcance sea demasiado amplio.
Johncorser

2
También me gustaría señalar el hecho de que esta pregunta es la misma pregunta para Objective-C y recibió más de 300 votos a favor y estaba protegida por moderadores (no puesta en espera como la mía). Creo que esta pregunta podría resultar muy valiosa para la comunidad.
Johncorser

6
Entendido. Soy un principiante en iOS y no he tenido la oportunidad de aprender el Objetivo C. La traducción puede ser fácil una vez que sabes cómo se hace, pero no sé cómo se hace. Es probable que muchas personas como yo utilicen el fragmento.
Johncorser

1
Claro, pero al menos, parece extraño estar escribiendo código Swift y referirse a las respuestas de Objective-C. Luego, el lector debe realizar la conversión en lugar de reutilizar un fragmento. La creación de un repertorio de respuestas Swift en StackOverflow solo será beneficioso para la comunidad en el futuro, ya que Swift puede convertirse eventualmente en el idioma principal en el que se escriben las aplicaciones de iOS.
Johncorser

2
La pregunta que vinculé tiene 6 años, pero el idioma Swift es mucho, mucho más joven. La versión rápida de la pregunta no podría haberse formulado hace seis años.
johncorser

Respuestas:


129

No estoy seguro de si realmente obtuviste la respuesta. Estaba en una búsqueda similar y encontré esta solución y la hice funcionar.

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
    }
}

¿Enviaría esto un mensaje de texto o iMessage?
Oren Edrich

2
Simplemente lo llevará a la aplicación de mensajería. La aplicación determina si es un mensaje o un iMessage.
sivag1

¿Cómo compartir URL y texto?
kishor0011

Considere actualizar para Swift para. Por ejemplo, ahora es: func messageComposeViewController (_ controller: MFMessageComposeViewController, ...)
crimson_penguin

funcionó para mí con poca edición. controller.recipients = ([self.phoneNumber.text] as! [String])
Rakshitha Muranga Rodrigo

29

Solución Swift 3.0:

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
    }

15

Para enviar iMessage en Swift 5 utilizo el siguiente código

Solo paquete MessageUI e implementar 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)
    }
}

Gracias, sin embargo, el mensaje emergente no se descarta, por lo que necesitaba agregar el controlador a la línea: controller.dismiss (animado: verdadero, finalización: nulo)
David Sanford

5

Si no desea depender de un UIViewController, siga una solución Swift 3.0 :

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()
    }
}

Llamas al compositor de esta manera:

let phoneNumber = "987654321"
let composer = MNMessageComposerBuilder()
composer.phoneNumber(phoneNumber).show()

o usando una var perezosa

let phoneNumber = "987654321"
private lazy var messageComposer: MNMessageComposerBuilder = {
    let composer = MNMessageComposerBuilder()
    return composer
}()
messageComposer.phoneNumber(phoneNumber).show()

5

Rápido 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;
        }
    }

La interfaz de usuario se verá así: ingrese la descripción de la imagen aquí


0

Una solución más simple puede ser abrir un enlace html:

let mPhoneNumber = "1111111111";
let mMessage = "hello%20phone";
if let url = URL(string: "sms://" + mPhoneNumber + "&body="+mMessage) {
    UIApplication.shared.open(url)
}

Asegúrese de reemplazar los espacios con "% 20"


-1
@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;
    }
}

Esto fallará en un simulador, porque no verifica canSendText(). Además, recipientsse coloca en la ventana de redacción. En la mayoría de los dispositivos, MMS permitirá que el texto del marcador de posición se vuelva verde, no coincida con un número en los contactos y luego permitirá que el usuario envíe un mensaje a su texto de muestra, que no irá a ninguna parte. (Es posible que le cueste un mensaje al usuario del dispositivo, si el operador cobra por él)
benc
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.