Your app can present an interface allowing the user to edit and send a mail message or an SMS message. Two view controller classes are provided by the Message UI framework; you’ll need to import MessageUI
. In addition, the Social framework lets you post to Twitter or Facebook on the user’s behalf. You’ll need to import Social
. The classes are:
UIActivityViewController (Chapter 13) also provides a unified interface for permitting the user to choose any of the built-in messaging milieus and to send a message through it. However, the Message UI framework and the Social framework remain important, because the user can be presented with a message form without having to pass through an activity view, and because you can fill in fields, such as the recipient field in a mail composition form, that UIActivityViewController doesn’t let you fill in.
Another option is to form a URL of the appropriate scheme and hand it to UIApplication’s openURL:
method. For example, given a mailto:
URL, openURL:
can generate a proposed mail message with an initial recipient field and subject field. (See the Apple URL Scheme Reference for a list of built-in URL schemes.) That takes the user to the Mail app — and out of your app — but in iOS 9 that might not be so terrible, because a Back button appears in the status bar.
The MFMailComposeViewController class, a UINavigationController, allows the user to edit a mail message. The user can attempt to send the message there and then, or can cancel but save a draft, or can cancel completely. Before using this class to present a view, call canSendMail
; if the result is false
, go no further, as a negative result means that the device is not configured for sending mail. A positive result does not mean that the device is connected to the network and can send mail right now, only that sending mail is generally possible with this device; actually sending the mail message (or storing it as a draft) will be up to the device’s internal processes.
To use MFMailComposeViewController, instantiate it, provide a mailComposeDelegate
(not delegate
) adopting MFMailComposeViewControllerDelegate, and configure the message to any desired extent. Configuration methods are:
setSubject:
setToRecipients:
setCcRecipients:
setBccRecipients:
setMessageBody:isHTML:
addAttachmentData:mimeType:fileName:
Typically, you’ll show the MFMailComposeViewController as a presented view controller. (On the iPad, a .FormSheet
presentation feels less overwhelming.) The user can later alter your preset configurations, at which time the message details will be out of your hands.
The delegate method mailComposeController:didFinishWithResult:error:
will be called, describing the user’s final action, which might be any of these:
MFMailComposeResultCancelled
MFMailComposeResultSaved
MFMailComposeResultSent
MFMailComposeResultFailed
Dismissing the presented view controller is up to you, in the delegate method. Here’s a minimal example:
@IBAction func doMail (sender:AnyObject!) { guard MFMailComposeViewController.canSendMail() else { return } let vc = MFMailComposeViewController() vc.mailComposeDelegate = self self.presentViewController(vc, animated:true, completion:nil) } func mailComposeController( controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) { // can do something with result here self.dismissViewControllerAnimated(true, completion: nil) }
The MFMessageComposeViewController class is a UINavigationController subclass. Before using this class to present a view, call canSendText
; if the result is false
, go no further. The user has no option to save an SMS message as a draft, so even if this device sometimes can send text, there’s no point proceeding if the device can’t send text now. However, you can register for the MFMessageComposeViewControllerTextMessageAvailabilityDidChangeNotification
in the hope that the device might later be able to send text; if the notification arrives, examine its MFMessageComposeViewControllerTextMessageAvailabilityKey
.
To use MFMessageComposeViewController, instantiate the class, give it a messageComposeDelegate
(not delegate
) adopting MFMessageComposeViewControllerDelegate, and configure it as desired through the recipients
(phone number strings) and body
properties. You can also configure the message subject and provide attachments. For the subject, call the class method canSendSubject
, and if it returns true
, you can set the subject
. For attachments, call the class method canSendAttachments
, and if it returns true
, you may want to call isSupportedAttachmentUTI:
to see if a particular file type can be sent as an attachment; finally, call addAttachmentURL:withAlternateFilename:
(if you have a file URL) or addAttachmentData:typeIdentifier:filename:
. Conversely, you can prevent the user from adding attachments by calling disableUserAttachments
.
When you’ve finished configuring the MFMessageComposeViewController, show it as a presented view controller. The user can later alter your preset configurations, at which time the message details will be out of your hands.
The delegate method messageComposeViewController:didFinishWithResult:
will be called with a description of the user’s final action, which might be any of these:
MessageComposeResultCancelled
MessageComposeResultSent
MessageComposeResultFailed
Dismissing the presented view controller is up to you, in the delegate method. Here’s a minimal example:
@IBAction func doMessage (sender:AnyObject!) { guard MFMessageComposeViewController.canSendText() else { return } let vc = MFMessageComposeViewController() vc.messageComposeDelegate = self self.presentViewController(vc, animated:true, completion:nil) } func messageComposeViewController( controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) { // can do something with result here self.dismissViewControllerAnimated(true, completion: nil) }
The interface for letting the user construct a Twitter post is SLComposeViewController, part of the Social framework. Twitter, together with Facebook (and Weibo), are represented by constant strings starting with SLServiceType
. You’ll use the class method isAvailableForServiceType:
to learn whether the desired service is available; if it is, you can instantiate SLComposeViewController for that service and present it as a presented view controller.
SLComposeViewController has a more modern API than the mail and message view controllers. Instead of a delegate, SLComposeViewController has a completionHandler
. Set it to a function taking one parameter, an SLComposeViewControllerResult. In the function, dismiss the view controller. The SLComposeViewControllerResult parameter will be .Cancelled
or .Done
. Here’s a minimal example:
@IBAction func doTwitter (sender:AnyObject!) { guard SLComposeViewController .isAvailableForServiceType(SLServiceTypeTwitter) else { return } guard let vc = SLComposeViewController( forServiceType:SLServiceTypeTwitter) else { return } vc.completionHandler = { (result:SLComposeViewControllerResult) in // can do something with result here self.dismissViewControllerAnimated(true, completion:nil) }; self.presentViewController(vc, animated:true, completion:nil) }
You can also, with the user’s permission, gain secure access to the user’s account information through the ACAccountStore class (part of the Accounts framework). Using this, along with the SLRequest class, your app can construct and post a message directly, without passing through the message composition interface. The ACAccountStore class can manipulate accounts in other ways as well, without violating the user’s privacy.
3.145.204.201