I was trying to send SMS from within my app. I wrote this piece of code but it seems not to work.
No crash, no error log, simply nothing happen (of course I tried to log canSendText and the result is 1).
- (void)viewDidLoad
{
[super viewDidLoad];
messageComposer = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText]) {
[messageComposer setBody:#"Messaggio generato da SMSTest"];
[messageComposer setRecipients:[NSArray arrayWithObject:#"3333333333"]];
[messageComposer setDelegate:self];
[self presentModalViewController:messageComposer animated:YES];
}
}
Can anyone explain me what I'm doing wrong?
The problem is that presentModalViewController does not work in viewDidLoad yet as the view is loaded but might not even be on screen yet. If you put your code in viewWillAppear:animated, this should work.
Edit: As per Saphrosit's comment: viewDidAppear: is an even better place to do this.
I use this successfully:
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
controller.messageComposeDelegate = self;
controller.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:controller animated:YES];
Note that it's messageComposeDelegate, not 'delegate' as you do.
Tim
When i try the code on simulator i get an UIAlert saying text messaging is not available, because simulator canĀ“t send messages. Have you checked that your header file is a delegate of MFMessageComposeViewControllerDelegate ?
YourClassName : UIViewController <MFMessageComposeViewControllerDelegate>
//try this ... it will run ..
MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
controller.body = #"Hello from Kartik";
controller.recipients = [NSArray arrayWithObjects:#"12356478", nil];
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
Related
I trying to write rhodes native extension extension for opening iOS MailComposer.
Now code "works", but MFMailComposeViewController not displaying and xcode shows warning:
Attempt to present <MFMailComposeViewController: 0x12b60840> on <Iosmailto: 0xc1898d0> whose view is not in the window hierarchy!
I read that UIViewControllers must be in hierarchy, but i can't provide this from Rhodes ruby code or clear-C extension wrapper.
Now i'm trying to present my UIViewController with MFMailComposeController from [UIApplication sharedApplication].keyWindow.rootViewController but mail composer not show yet.
interface from iosmailto.h:
#interface Iosmailto : UIViewController<MFMailComposeViewControllerDelegate>
{
}
#property(nonatomic, assign) id delegate;
//-(IBAction)send_mail:(id)sender;
#end
implementation from iosmailto.m:
#implementation Iosmailto
- (void)viewDidLoad {
[super viewDidLoad];
[self send_mail];
}
- (void)send_mail {
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:[NSString stringWithUTF8String:subj]];
NSArray *recipients_array = [NSArray arrayWithObject:[NSString stringWithUTF8String:recipients]];
[composer setToRecipients:recipients_array];
NSString *composerBody = [NSString stringWithUTF8String:message];
[composer setMessageBody:composerBody isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:composer animated:YES];
[composer release];
} else {
NSLog(#"Device is unable to send email in its current state.");
}
}
/* some unnecessary for this question methods */
#end
And C function defined in iosmailto.m thats called from Rhodes:
// find root vc
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
// find topmost vc
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
iosmailer = [[Iosmailto alloc] init];
iosmailer.delegate = topController;
[topController presentViewController:iosmailer animated:YES completion:nil];
This app is not for AppStore. Hacks is welcome if needed.
Update init for Iosmailto:
- (id)init
{
self = [super initWithNibName:nil bundle:nil];
return self;
}
Update 2 The short version of this code (without UIViewController wrapper) was my starting point. That's don't work too. And this have the same warning and one more:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = (id<MFMailComposeViewControllerDelegate>)topController ;
[composer setSubject:[NSString stringWithUTF8String:subj]];
NSArray *recipients_array = [NSArray arrayWithObject:[NSString stringWithUTF8String:recipients]];
[composer setToRecipients:recipients_array];
NSString *composerBody = [NSString stringWithUTF8String:message];
[composer setMessageBody:composerBody isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[topController presentModalViewController:composer animated:YES];
[composer release];
} else {
}
Use this code to present view controller
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:composer
animated:YES
completion:nil];
Ok I think the problem is that your UIViewController doesn't have anything in its view property because you aren't using a .xib file to initialize it. See this question which programmatically creates a UIView and assigns it to the UIViewController's view property. I think that's the right way to go. See the implementation of their -(void)loadView method.
Your use-case is also a little strange, since it looks like your Iosmailto UIViewController doesn't have any content, and you're just using it as a wrapper around MFMailComposeViewController--you might consider reimplementing your C method to directly create a MFMailComposeViewController without the unnecessary layer of indirection of this unnecessary UIViewController that doesn't display anything itself.
I have an iOS TabBar Application with tabbarcontroller and navigationcontroller.
In my detail view wich is pushed from my first tab tableviewcontroller i have sharing navigationItem.rightBarButtonItem with email sharing.
I have the following code for this:
- (void)share
{
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:#"Send" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Email",nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
[popupQuery showInView:self.view];
[popupQuery release];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
if ([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
[picker setMailComposeDelegate:self];
[picker setSubject:#"New theme"];
NSString *emailBody = #"Hi there";
[picker setMessageBody:emailBody isHTML:NO];
[self resignFirstResponder];
picker.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
picker.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:picker animated:NO];
[picker release];
}
else{
}
}
}
The app shows me the composing view but when i'm trying to do something with this view (e.g. to pick up the address or to spell something) - app crashes with SIGTRAP.
The app crashes only in iOS5, iOS5.1. In iOS4.2.1 everything works perfect.
What's the problem? Any ideas?
Per the docs, I'd suggest calling [MFMailComposeViewController canSendMail] class method before creating MFMailComposeViewController. I also generally don't have that [self resignFirstResponder] line. I gather you're crashing before your mailComposeController:didFinishWithResult:error method is invoked?
Thank you guys for your help and your time.
It was absolutely insane bug. Project has a cyrillic name. I just renamed it to latin name and now everything works fine. My fault :( Thanks Evgeniy Shurakov for the help.
I have a method like this:
void sendSMS{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.recipients = [NSArray arrayWithObject:#"0933660805"];
[picker setBody:#"Message body"];
picker.messageComposeDelegate = self;
[self.navigationController presentModalViewController:picker animated:YES];
//[picker release];
return;
}
}
Message composer open but recipients and message body are empty (image below). Anybody know how can i fix it :(
Go for this ones and then check may be it will resolve your issue
void sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSMutableArray *toRecipients = [[NSMutableArray alloc]init];
[toRecipients addObject:#"0933660805"];
[picker setRecipients:(NSArray *)toRecipients];
[toRecipients release];
bodyString = [NSString stringWithFormat: #"Message body"];
[picker setBody:bodyString];
[self presentModalViewController:picker animated:YES];
[picker release];
}
Also take a look at this tutorial http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/
Good Luck!
OK I answered my own question. Now I want no one else to have to go thru this. I was calling this method from just an NSObject. It was a delegate to MFMessageComposeViewControllerDelegate but that made no difference. I had to move this method to my MainViewController, then it worked.
iOS 10.0 is here and this is still a problem for me. So, I have fashioned a workaround.
According to previous comments that initializing the MFMessageComposeViewController in the viewDidLoad() won't solve the problem (which I can attest to), unless the view controller gets presented, it won't be cached. So, the hack here is to make a window, set its root view controller, present a dummy MFMessageComposeViewController instance and immediately dismiss it, somewhere before your actual need (like in viewDidLoad())
Here is a sample code I'm using (Swift 3.0 - Let me know if you were interested in Obj-C counterpart):
let window = UIWindow()
let vc = UIViewController()
window.rootViewController = vc
let messageCompose = MFMessageComposeViewController()
vc.present(messageCompose, animated: false) { [weak messageCompose] in
messageCompose?.dismiss(animated: false, completion: nil)
}
The thing here is that if you present it in the currently active window's view controller chain, it will mess up your UI by showing and hiding the keyboard abruptly (no matter how you try to hide the controller's view and what not), due to the message body selection on present. But adding it to a whole new window which is not in view cycle, it will be correctly initialized and there will be no trace of such transaction on view. Plus, you won't boggle the memory too much this way (because the scope of the controller should be minimal now) and you can initialize your actual MFMessageComposeViewController any time you want and get it much faster now. If your application heavily relies on MFMessageComposeViewController (which I doubt) you can move this to your AppDelegate to be ready anywhere around your app's life cycle.
Cheers,
M.
Try this
- (void)sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSArray *toRecipients = [NSArray arrayWithObject:#"NUMBER HERE"];
[picker setRecipients:toRecipients];
[self presentModalViewController:picker animated:YES];
[picker release];
}
In my case (on iPhone 3g s) the problem was when I called [self.navigationController pushViewController... ], when i tried call [self presentModalViewController ...] it worked, I dont know why, but it is. Try it.
set the MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
before if ([MFMessageComposeViewController canSendText]) {...}
Try this.
Try this.
- (void)forwardPromo
{
MFMessageComposeViewController *composeViewController = [[MFMessageComposeViewController alloc] init];
composeViewController.body = #"Message body";
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805"];
composeViewController.messageComposeDelegate = self;
[self presentViewController:composeViewController animated:YES completion:nil];
}
You should have a "nil" at the end of the array:
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805", nil];
Iphone 4 MFMailComposeViewController
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setMessageBody:#"Welcome" isHTML:NO];
[controller release];
My app to be crash.
Wat i did wrong
Regards,
Arun
The mail composer will crash if the user is unable to send mail. First check to see if the user is able to send mail before trying to instantiate a MFMailComposeViewController.
if([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController* controller = [[[MFMailComposeViewController alloc] init] autorelease];
//...
}
#Arun , First up all configure the email settings in your device
As Akira says, you can use MFMailComposeViewController after you set up the device's e-mail settings.
init failed, because not iOS mail-application's setting.
MFMailComposeViewController* controller = [[[MFMailComposeViewController alloc] init] autorelease];
if (!controller) // failed
return; // auto view alert, "not mail setting..."
controller.mailComposeDelegate = self;
I am writing code to send sms programatically
Program crashes at second last line.
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
picker.recipients = [NSArray arrayWithObject:#"123456789"]; // your recipient number or self for testing
picker.body = #"test from OS4";
[self presentModalViewController:picker animated:YES];
[picker release];
I assume it's safe to say that it implements
UIViewController <MFMessageComposeViewControllerDelegate>
In which case, I would recommend going back to http://iphonesdkdev.blogspot.com/2010/04/mfmessagecomposeviewcontroller-sample.html, copying their example and progressing from there.