用 Swift 在 iOS 上发短信

首先,我很惊讶这不是一个复制品,因为在 Objective-C 中有成千上万的堆栈溢出问题可以解决这个问题,但是我还没有看到一个使用 Swift 的好答案。

我要找的是 Swift 中的一个代码片段,它将一个任意的字符串作为文本消息的正文发送给给定的电话号码。本质上,我希望像 这个从苹果的官方文档,但在 Swift 而不是 Objective-C。

我想这并不太难,因为在 Android 中只需要几行代码就可以完成。

编辑: 我正在寻找的是5-20行的 Swift 代码,我不同意这是太广泛。在 Java (Android)中,解决方案是这样的:

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

这是机器人的解决方案,只有11行。Java 往往比 Swift 冗长得多,所以我怀疑我的问题是“太宽泛”,更有可能的是我不知道如何使用 Objective-C MessageComposer 对象,因为我链接到上面的文档不清楚在 Swift 中的用法。

70261 次浏览

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

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: enter image description here

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

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"