I have a webview object (aWebView) which was added on top of current window like this -
UIWindow *webWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 20, 320,460)];
[webWindow addSubview:aWebView];
[webWindow makeKeyAndVisible];
I have a ViewController (viewcontrollerobj) which is subView of aWebView -
[webView addSubview:viewcontrollerobj.view];
Then I am calling sendInAppMail method in the ViewController-
[sviewcontroller sendInAppMail];
SendInAppMail looks like this -
MFMailComposeViewController *mailController = [[[MFMailComposeViewController alloc] init] autorelease];
if([MFMailComposeViewController canSendMail])
{
[mailController setMessageBody:#"hello" isHTML:NO];
[mailController setSubject:#"subject"];
mailController.mailComposeDelegate = self;
[self presentModalViewController:mailController animated:YES];
[mailController release];
}
didFinishWithResult looks like this -
- (void)mailComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSent:
break;
default:
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Mail viewcontroller shows up fine. The problem is that when I hit cancel it shows the delete/save draf t option and after clicking either delete/save the mail viewcontroller doesn't go away!
When I look at console it shows this log message -
"Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:]."
I am not using UIActionSheet anywhere and haven't used in the past so I am not able to understand what it is saying.
I looked at this - https://stackoverflow.com/a/6015957/516938
But it seems like the solution given is very specific to a situation.
Not sure this is the issue, but this is the first thing I would look at.
Based on the error message that you got it sounds like either one of the views (the aWebView or the one from viewcontrollerobj that you defined) doesn't allow enough space for the MFMailComposeViewController, meaning that the dimensions of it are smaller than the MFMailComposeViewController requires. It isn't actually clipping the content, so you see it, but it is blocking the touches so that they don't get to the MFMailComposeViewController.
I hope that is clear enough - I had a hard time describing my thoughts here correctly.
Related
Essentially I'm working with 3 view controllers.
Main view which starts a download. (Webview based which passes the download).
Modal download controller. (Tab based).
Downloader (HCDownload).
In the main view my download gets passed like so:
//Fire download
[activeDL downloadURL:fileURL userInfo:nil];
[self presentViewController:vc animated:YES completion:nil];
activeDL is initialized in viewDidLoad:
activeDL = [[HCDownloadViewController alloc] init];
If I removed the presentViewController, it still downloads, which is fine. Then i tap my Downloads button, it brings up the controller which defines the tabs like so:
center = [[CenterViewController alloc] init];
activeDL = [[HCDownloadViewController alloc] init];
completedDL = [[DownloadsViewController alloc] init];
activeDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Active Downloads"
image:nil //[UIImage imageNamed:#"view1"]
tag:1];
completedDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Completed Downloads"
image:nil //[UIImage imageNamed:#"view3"]
tag:2];
[self setViewControllers:[NSArray arrayWithObjects:activeDL, completedDL, nil]];
However, it is not passing the current active download. I don't know if it's a initialization problem, or my tab issue of showing the current download.
From his github, he suggests to get the current number of downloads is to call: dlvc.numberOfDownloads which for me would be
[activeDL numberOfDownloads].
I call this in the the Downloader viewWillAppear but nothing shows.
Does anybody has any suggestions or have worked with this controller?
Any help would be appreciated.
When you call:
activeDL = [[HCDownloadViewController alloc] init];
You are creating a new download controller, which has its own internal downloads array. This library, as written, has no way to pass this information from one HCDownloadViewController object to another.
Tying downloads to VC's like this will cause problems -- I recommend you rewrite this code to split that apart.
To hack around it, try to create just one HCDownloadViewController object and pass it around.
Ok so with the last comment of the other answer, "Make activeDL a member variable instead of a local variable.", got me Googling and with some tinkering and bug fixing along the way I managed to get it all up and running perfect.
I declared it all in my AppDelegate.
AppDelegate.h
#interface SharedDownloader : HCDownloadViewController <HCDownloadViewControllerDelegate>
+ (id)downloadingView;
#end
AppDelegate.m
static HCDownloadViewController *active;
#implementation SharedDownloader
+ (id)downloadingView {
if (active == nil)
active = [[HCDownloadViewController alloc] init];
return active;
}
#end
Calling to the class for downloading in my main view controller:
-(id)init{
activeDL = [SharedDownloader downloadingView];
return self;
}
//Spot where I fire the download
if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
//More code here
[activeDL downloadURL:fileURL userInfo:nil];
}
Lastly in my tab bar controller:
-(id)init {
activeDL = [SharedDownloader downloadingView];
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
activeDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Active Downloads" image:nil] tag:2];
}
I believe that's all of it. In any case, thanks to Lou Franco for pointing me in the right direction.
How do I send a text message (using MFMessageComposeViewController) directly via an IBAction? Like, when the button is pressed, a text message is sent with a preset number, and no keyboard shows up or anything. Just an alert saying "SMS was sent successfully," for example.
All the coding is done, except for this "direct sending-function".
Well, you can't technically "auto-send" the message, because it will require user confirmation to go through.
You can, however, set up the message's contents and recipient(s) using MFMessageComposeViewController (quite a mouthful) and display a dialog that will require one extra tap to send.
To have access to that dialog, you'll have to #import <MessageUI/MessageUI.h> and add MFMessageComposeViewControllerDelegate to your view controller declaration in your header file.
Then, you can write the IBAction. First, you want to check that the device can actually send messages with text content using canSendText. Then, you'll create the view controller, populate it with data, and present the dialog.
- (IBAction)sendMessage:(UIButton *)sender {
if([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init]; // Create message VC
messageController.messageComposeDelegate = self; // Set delegate to current instance
NSMutableArray *recipients = [[NSMutableArray alloc] init]; // Create an array to hold the recipients
[recipients addObject:#"555-555-5555"]; // Append example phone number to array
messageController.recipients = recipients; // Set the recipients of the message to the created array
messageController.body = #"Example message"; // Set initial text to example message
dispatch_async(dispatch_get_main_queue(), ^{ // Present VC when possible
[self presentViewController:messageController animated:YES completion:NULL];
});
}
}
One last thing: you have to implement a delegate method to tell the message view controller to dismiss when the user presses "cancel" in the send dialog:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
[self dismissViewControllerAnimated:YES completion:NULL];
}
I'm trying to track down the source of a bug in a cordova/phonegap plugin I wrote for creating email messages in app using a MFMailComposeViewController instance.
Everyone works fine the first time you present the the composer view. The user can dismiss the mail composer by sending the message or canceling. However, call presentViewController again renders the Cancel and Send buttons in the composer to become useless. My delegate for didFinishWithResult is never calling when pressing the inoperable buttons with the second view of the controller.
Below is simplified repro of what I'm seeing (the simple storyboard has a single view containing a single UIButton wired to my (IBAction)sendMail). What am I doing wrong in obj-c here? Shouldn't I be able to show a controller, dismiss it, and show it again?
ViewController.h:
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#interface ViewController : UIViewController
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController () <MFMailComposeViewControllerDelegate>
#property (nonatomic, weak) IBOutlet UIButton *mailButton;
#property(nonatomic, strong) MFMailComposeViewController* picker;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.picker = [[MFMailComposeViewController alloc] init];
self.picker.mailComposeDelegate = self;
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (IBAction)sendMail
{
[self presentViewController:self.picker animated:YES completion:NULL];
}
#end
The reason for the behavior you are experiencing is the MFMailComposeViewController nils it's delegate when dismissed (maybe in -viewDidDisappear:).
- (void)viewDidLoad
{
[super viewDidLoad];
self.picker = [[MFMailComposeViewController alloc] init];
self.picker.mailComposeDelegate = self;
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// Put a break point here **#breakpoint1**
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (IBAction)sendMail
{
// Put a break point here **#breakpoint2**
[self presentViewController:self.picker animated:YES completion:NULL];
}
Place breakpoints at shown in the code comment above, run, and follow me as we step through your code.
Tap the interface button that calls your IBAction; execution halts at #breakpoint2
In the console type po self.picker
You'll see the mail compose VC instance is allocated
In the console type po self and then po self.picker.delegate
You'll see these both print the same object (the instance of your view controller)
Resume running, and tap the dismiss button on the mail compose view; execution halts at #breakpoint1
If you want to, inspect local and instance variables in console and then resume running
Tap the interface button that calls your IBAction (this is the second time); execution halts at #breakpoint2
In the console typ po self.picker.delegate
nil is printed to console
This delegate nil'ing behavior isn't documented in either Apple's MFMailComposeViewController class reference or the classes header. It's probably worth filing a bug report requesting clarification and better documentation. Because it's undocumented, the behavior may change in future releases. For that reason, the suggestions to create and destroy the VC as needed certainly seem like good common sense.
This bit me once before. It's caused by the composer being deallocated after it's done being dismissed. To solve this I would place the composer's creation either in viewDidAppear:, or in sendMail as Fahim suggested.
Additionally, you may want to consider wrapping these two lines in [MFMailComposeViewController canSendMail];
I would say take below lines to sendMail... it would work.
self.picker = [[MFMailComposeViewController alloc] init];
self.picker.mailComposeDelegate = self;
You will have as below.
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)sendMail
{
self.picker = [[MFMailComposeViewController alloc] init];
self.picker.mailComposeDelegate = self;
[self presentViewController:self.picker animated:YES completion:NULL];
}
#end
This is working with me...
My App got rejected and reason is below:-
Did not integrate with iOS features. For example, the email button should enable users to compose emails in the app rather than launching the Mail app.
I did not get that what they want. I have used MFMailComposer class so what's wrong with it?Any Suggestion.
Did you do it like this:
- (IBAction)pushMail:(id)sender { //A button that initiates composition
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"My Mail Subject"];
if (controller) [self presentModalViewController:controller animated:YES];
[controller release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
{
if (result == MFMailComposeResultSent) {
NSLog(#"It's away!");
}
[self dismissModalViewControllerAnimated:YES];
}
I think you have to use an MSMailComposeViewController (as I have in the above example) to do what you want.
... the email button should enable users to compose emails in the app ...
They mean that your program should allow people to compose emails, instead of opening Mail.app.
I am using MFMailComposeViewController in my app and the mail sending part seems to be OK.
But when I leave the mail app, things go wrong :
- one toolbar (UIToolbar object) has disappeared.
- one pointer (UIImageView*) has become nil, without me doing anything for that to happen.
In other words the calling environment is changed although I do not want it to change.
Where could be my mistake?
Here is my code, in case someone can see something wrong :
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
{
[controller dismissModalViewControllerAnimated:YES];
}
-(IBAction)sendAsEMail {
MFMailComposeViewController *mailComposeViewController=[[MFMailComposeViewController alloc] init];
mailComposeViewController.mailComposeDelegate=self;
[mailComposeViewController setSubject:#"Mail subject"];
[mailComposeViewController setMessageBody:#"This is for you !" isHTML:NO];
[mailComposeViewController addAttachmentData:
[NSData dataWithContentsOfFile:[[My_ViewController getDocDir] stringByAppendingPathComponent:
[pictureNames objectAtIndex:userItemSelected]]]
mimeType:#"image/png" fileName:#"Picture.png"];
if (mailComposeViewController) [self presentModalViewController:mailComposeViewController animated:YES];
[mailComposeViewController release];
}
Thanks for any piece of relevant information.
Try out this link it explain in detail
Add framework
Then .h file header files
Then .m file the mail code
Check at this link.