In my iPhone application, I have just implemented in-app SMS functionality. SMS functionality is working fine. But after opening MFMessageComposeViewController, if user wants to cancel sending sms, they have no option. The only option left is to send an sms, then only return on previous view. There should be a cancel button on navigation bar just as it is in the email composer. Below is the line of code that I wrote to have in-app sms functionality:
-(void) smsComposer{
MFMessageComposeViewController *_smsCompose = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText]) {
_smsCompose.body = #"SMS BODY";
_smsCompose.messageComposeDelegate = self;
[self presentModalViewController:_smsCompose animated:YES];
}
}
Is there anything that I am missing?
Thanks in advance,
PC
Try This....
in .h file
#import <MessageUI/MFMessageComposeViewController.h>
and
#interface TestViewController : UIViewController <MFMessageComposeViewControllerDelegate>
And then Button Click method
-(void)buttonPressed:(UIButton *)button
{
[self sendSMS:#"Body of SMS..." recipientList:[NSArray arrayWithObjects:#"+1-111-222-3333", #"111-333-4444", nil]];
}
MFMessageComposeViewController to create the SMS content and another method for handling the user interaction with the SMS dialog.
-(void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
And
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
if (result == MessageComposeResultCancelled)
NSLog(#"Message cancelled")
else if (result == MessageComposeResultSent)
NSLog(#"Message sent")
else
NSLog(#"Message failed")
}
And remember: You cannot send SMS messages from within the simulator. Test on Device.
Related
I have a simple app, which opens a modal view to send email. Am using Xcode 4.2 and iOS 5, and am testing with iOS Simulator. The app crashes with
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'Application tried to present a nil modal view controller on target
.'
when executing the line:
[self presentModalViewController:mailComposer animated:YES];
though I have initialized the object 'mailComposer'.
Class com_FirstViewController.m :
#import "com_FirstViewController.h"
...
#implementation com_FirstViewController
....
....
-(void)showEmailComposer {
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
if ([mailClass canSendMail]) {
NSLog(#"showEmailComposer: Calling displayComposerSheet");
[self displayComposerSheet];
} else {
NSLog(#"showEmailComposer: Calling launchMailAppOnDevice");
[self launchMailAppOnDevice];
}
}
else {
NSLog(#"showEmailComposer: Calling launchMailAppOnDevice");
[self launchMailAppOnDevice];
}
}
#pragma mark -
#pragma mark Compose Mail
-(void) displayComposerSheet {
mailComposer = [[MFMessageComposeViewController alloc] init];
mailComposer.messageComposeDelegate = self;
// Set the mail title
[mailComposer setTitle:#"Mail Title"];
// Set the recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"user#company.com"];
[mailComposer setRecipients:toRecipients];
// EMail Body
NSString *mailBody = #"This is the mail body";
[mailComposer setBody:mailBody];
NSLog(#"present the modal view ctlr");
[self presentModalViewController:mailComposer animated:YES];
}
...
...
Any pointers please?
I have also encountered a similar problem. I allocated an instance of MFMailComposeViewController and tried to present it modally. I also got an exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target
This was because the Mail option was disabled in the settings of the iPhone. It can be the case also when no mail account is set up in the device. So the MFMailCompseViewController instance will be nil and presenting it modally will cause the crash.
I used the canSendMail method of the MFMailComposeViewController to get around this issue.
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil) {
MFMailComposeViewController * mailView = [[MFMailComposeViewController alloc] init];
mailView.mailComposeDelegate = self;
//Set the subject
[mailView setSubject:emailSubject];
//Set the mail body
[mailView setMessageBody:emailBody isHTML:YES];
//Display Email Composer
if([mailClass canSendMail]) {
[self.navControl presentModalViewController:mailView animated:YES];
}
}
mailComposer = [[MFMessageComposeViewController alloc] init];
is the source of the problem, in my opinion. There's no way the simulator can send SMS messages, so the initializer method may return NULL. Anyways, sou seem to be wanting to send an email, so I'd say you need to use
mailComposer = [[MFMailComposeViewController alloc] init];
So, using the new Twitter framework in iOS5, we can simply post Twitter updates with this simple code:
if ([TWTweetComposeViewController canSendTweet]) {
TWTweetComposeViewController *tweetSheet = [[TWTweetComposeViewController alloc] init];
[tweetSheet setInitialText:#"Tweeting from Steamerduck :)"];
[controller presentModalViewController:tweetSheet animated:YES];
}
However, I would like to execute some custom code after a user clicks on send here:
Is it possible to execute some custom code, some of my own methods after the TWTweetComposeViewController sends a tweet?
You can specify a completion handler that gets called after the user is done composing the tweet. It would look something like this (I haven't had a chance to test this on a device yet):
if ([TWTweetComposeViewController canSendTweet]) {
TWTweetComposeViewController *tweetSheet = [[TWTweetComposeViewController alloc] init];
[tweetSheet setInitialText:#"Tweeting from Steamerduck :)"];
// Set a completion handler to be called when the user is done
// composing their tweet
[tweetSheet setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
if (result == TWTweetComposeViewControllerResultDone) {
// Tweet was sent, do something
} else if (result == TWTweetComposeViewControllerResultCancelled) {
// Do something else if the user cancelled
[controller dismissModalViewControllerAnimated:YES];
}
}];
[controller presentModalViewController:tweetSheet animated:YES];
}
With the SDK / Cocoa Touch, is it feasible to make an app that will SMS automatically?
My objective isn't to SPAM anyone.
It is not possible, exactly for the reason you mentioned: it would make spamming possible.
You would need a server that would handle the SMS for you, and an API for the app to interact with that server. It's not possible to have your app send messages directly from the phone, but you can certainly have your app interact with an external service that will send the messages for you.
Three is a way to pre-build an SMS using MFMessageComposeViewController. The only issue with this method is that a modal view will be shown to the user to accept the SMS (like the window that sends an e-mail by the default way). There is no way to send a SMS in "silent mode" without jailbreak.
{
...
[self sendSMS:#"_SMS_TEXT_" recipientList:[NSArray arrayWithObjects:#"PHONE_NUMBER", nil]];
...
}
- (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
if (result == MessageComposeResultCancelled)
NSLog(#"Message cancelled")
else if (result == MessageComposeResultSent)
NSLog(#"Message sent")
else
NSLog(#"Message failed")
}
I am using xcode 4.2 and i am developing an iphone APP , part of this app is sending SMSs
here is the code that I typed:
-(IBAction)SMSbutton{
MFMessageComposeViewController *sms = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText]) {
sms.body= [NSString stringWithFormat: #"text"];
sms.messageComposeDelegate = self;
[self presentModalViewController:sms animated:YES];
}
I can open the SMS application and send SMS but the problem is whether I click on the "cancel" or the "send" button the message application does not go away . how to do that ?
thanks
Set your calling class to be a delegate of the message composer, then catch the cancel and send events to dismiss the modal view controller as needed.
Set your header file to adhere to the MFMessageComposeViewControllerDelegate, and when you initialize the composer, set the message delegate to self:
MFMessageComposeViewController *george = [MFMessageComposeViewController alloc] init];
george.messageComposeDelegate = self;
Then implement the delegate method...easiest way is:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
}
...but you can catch and deal with errors and events as necessary.
Implement messageComposeViewController:didFinishWithResult: in your delegate"
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
if(result == MessageComposeResultCancelled) {
//Message cancelled
} else if(result == MessageComposeResultSent) {
//Message sent
}
[self dismissModalViewControllerAnimated:YES];
}
Have you tried dismissViewControllerAnimated:completion: or dismissModalViewControllerAnimated:?
[self dismissModalViewControllerAnimated: YES];
This issue is something which has me stumped, so hopefully someone can help. I have an UIActionSheet on a view which has three options in. One which takes my user to a new view, one to share via email and one to share via SMS.
I have the UIActionSheet created which works without issue, the new view part of the AlertSheet also works. I have imported the Message.UI framework and set up the mail and SMS pickers and composers which are fine. However, I am having trouble setting the two 'buttons' on the UIActionSheet to open up the mail and SMS.
Normally i would do this through interface builder and connect a UIButton to the actions I have created, but because this is a UIActionSheet it can't be done that way. Sorry for the LONG code but I felt I needed to show everything, so please see below;
-(IBAction)showActionSheet {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Choose an Option" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Application Support",#"Share Via Email",#"Share Via SMS",nil];
[actionSheet showInView:self.view];
[actionSheet release];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0) {
AppSupportView *controller = [[AppSupportView alloc] initWithNibName:#"AppSupportView" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
if(buttonIndex == 1) {
}
if(buttonIndex == 2) {
}
}
- (void)dealloc {
[feedbackMsg release];
[super dealloc];
}
- (void)viewDidUnload {
self.feedbackMsg = nil;
}
-(IBAction)showMailPicker:(id)sender {
// The MFMailComposeViewController class is only available in iPhone OS 3.0 or later.
// So, we must verify the existence of the above class and provide a workaround for devices running
// earlier versions of the iPhone OS.
// We display an email composition interface if MFMailComposeViewController exists and the device
// can send emails. Display feedback message, otherwise.
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil) {
//[self displayMailComposerSheet];
// We must always check whether the current device is configured for sending emails
if ([mailClass canSendMail]) {
[self displayMailComposerSheet];
}
else {
feedbackMsg.hidden = NO;
feedbackMsg.text = #"Device not configured to send mail.";
}
}
else {
feedbackMsg.hidden = NO;
feedbackMsg.text = #"Device not configured to send mail.";
}
}
-(IBAction)showSMSPicker:(id)sender {
// The MFMessageComposeViewController class is only available in iPhone OS 4.0 or later.
// So, we must verify the existence of the above class and log an error message for devices
// running earlier versions of the iPhone OS. Set feedbackMsg if device doesn't support
// MFMessageComposeViewController API.
Class messageClass = (NSClassFromString(#"MFMessageComposeViewController"));
if (messageClass != nil) {
// Check whether the current device is configured for sending SMS messages
if ([messageClass canSendText]) {
[self displaySMSComposerSheet];
}
else {
feedbackMsg.hidden = NO;
feedbackMsg.text = #"Device not configured to send SMS.";
}
}
else {
feedbackMsg.hidden = NO;
feedbackMsg.text = #"Device not configured to send SMS.";
}
}
// Displays an email composition interface inside the application. Populates all the Mail fields.
-(void)displayMailComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"My BMR Index Rating from Total:Health App"];
// Set up recipients
//NSArray *toRecipients = [NSArray arrayWithObject:#""];
//[picker setToRecipients:toRecipients];
NSString *emailSharing = #"I Just discovered that I have a Target Heart Rate of";
// Fill out the email body text
[picker setMessageBody:emailSharing isHTML:YES];
[self presentModalViewController:picker animated:YES];
[picker release];
}
// Displays an SMS composition interface inside the application.
-(void)displaySMSComposerSheet
{
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *SMSShare = #"I Just discovered that I have a Target Heart Rate of";
// Fill out the email body text
picker.body = SMSShare;
[self presentModalViewController:picker animated:YES];
[picker release];
}
// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the
// message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
feedbackMsg.hidden = NO;
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
feedbackMsg.text = #"Result: Mail sending canceled";
break;
case MFMailComposeResultSaved:
feedbackMsg.text = #"Result: Mail saved";
break;
case MFMailComposeResultSent:
feedbackMsg.text = #"Result: Mail sent";
break;
case MFMailComposeResultFailed:
feedbackMsg.text = #"Result: Mail sending failed";
break;
default:
feedbackMsg.text = #"Result: Mail not sent";
break;
}
[self dismissModalViewControllerAnimated:YES];
}
// Dismisses the message composition interface when users tap Cancel or Send. Proceeds to update the
// feedback message field with the result of the operation.
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
feedbackMsg.hidden = NO;
// Notifies users about errors associated with the interface
switch (result)
{
case MessageComposeResultCancelled:
feedbackMsg.text = #"Result: SMS sending canceled";
break;
case MessageComposeResultSent:
feedbackMsg.text = #"Result: SMS sent";
break;
case MessageComposeResultFailed:
feedbackMsg.text = #"Result: SMS sending failed";
break;
default:
feedbackMsg.text = #"Result: SMS not sent";
break;
}
[self dismissModalViewControllerAnimated:YES];
}
#end
The issue is obviously that I dont know how to proceed with the (if buttonIndex ==1) etc piece of code to open the mail and SMS
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0) {
AppSupportView *controller = [[AppSupportView alloc] initWithNibName:#"AppSupportView" bundle:nil];
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
if(buttonIndex == 1) {
}
if(buttonIndex == 2) {
}
}
Any help would be appreciated.
Thanks
looks like all your needed methods are there already..
just add [self showMailPicker:nil] or [self showSMSPicker:nil] to
if(buttonIndex == 1) {
}
if(buttonIndex == 2) {
}
if your second button from the top is your sms button, add showSMSPicker to buttonIndex == 1