I am using QLPreviewController for showing the pdf. And I am sending pdf by tapping the share button and then tap on email in the QLPreviewController.
But i don't know how to get that share button method in QLPreviewController to validate that the email account is available or not. Here is the screenshot:
Please let me know about this.
Thanks in advance.
if you have UInavigationController then you can add a bar button for sharing the content. Or you can add a share button in your viewcontroler.
Use MessageUI. Add the delegates MFMessageComposeViewControllerDelegate, MFMailComposeViewControllerDelegate.
- (IBAction)contactBtn:(id)sender {
if ([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
[controller setSubject:#"Subject"];
[controller setMessageBody:#" " isHTML:NO];
[controller setToRecipients:[NSArray arrayWithObjects:#"a#wa.com",nil]];
controller.mailComposeDelegate = self;
[self presentViewController:controller animated:YES completion:NULL];
}
else{
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Failed!" message:#"Mail can not be sent. Check your email settings." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil] ;
[alert show];
}
}
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[self dismissViewControllerAnimated:YES completion:NULL];
}
The QL previewer is working on separate process. Something like a different app. So there is no way to customize the share button. see details here
This may help you. See this answer.
Related
I am using MFMailComposeViewController in my application to compose a feedback E-Mail. The MFMailComposeViewController gets displayed, but can't be closed.
Method used to open the MFMailComposeViewController modal window:
-(IBAction) feedbackBtnClicked:(id)sender {
// Dismiss the Old View Controller
[self dismissViewControllerAnimated:NO completion:NULL];
// Present the New View Controller
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:#"Sample Subject"];
[mail setMessageBody:#"Here is some main text in the email!" isHTML:NO];
[mail setToRecipients:#[#"example#mail.com"]];
[self presentViewController:mail animated:YES completion:NULL];
}
else
{
NSLog(#"This device cannot send email");
}
}
Here is what happens, when clicking on the buttons:
Senden (Send) - The E-Mail gets sent, but the modal window stays open; clicking on that button multiple times results in sending multiple E-Mails without the modal window ever getting closed.
Abbrechen (Cancel) - Nothing happens
How to dismiss make sure the MFMailComposeViewController gets dismissed after clicking on those buttons?
You need to implement the MFMailComposeViewControllerDelegate method mailComposeController:didFinishWithResult:error:, and dismiss the mail view controller…
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
UIAlertView delayed or not showing up when pass another view. Any help would be greatly appreciated.
-(void)viewDidLoad{
levelContentController = [[UIAlertView alloc] initWithTitle:#""
message:#"Loading...
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
}
-(void)passToTestView:(id)sender{
[levelContentController show];
ViewController *viewController = [[ViewController alloc]init];
clickedLevelId = [[NSString alloc] init];
clickedLevelId = [testIdStringArray objectAtIndex:[sender tag]-1];
[viewController sendIndexMethod:sendIndex];
[viewController testCompletedArrayMethod:arrayOfCompletedTest];
[viewController parseTestURL:buttonTag getTestIdString:clickedLevelId];
viewController.viewSoundCheck = _levelSoundCheck;
[self presentViewController:viewController animated:YES completion:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[levelContentController dismissWithClickedButtonIndex:0 animated:YES];
}
The above code has some problems.
When passToTestView: selector is called, it'll try to present the alertView. But within the same method you are trying to present another view controller.
This will in turn call viewWillDisappear: where you are hiding the alertView.
It's recommended that if you want to present the alertView while displaying ViewController, create and display UIAlertView instance in the ViewController class's viewDidLoad or viewWillAppear:. Do not initialise and display it in this viewController.
To make the UIAlertView appear, you should call:
[contentLoadingController show];
Note that UIAlertView is deprecated in iOS9, and you should use UIAlertController.
I have this simple function to write mail on ios 8.0, xcode 6.1. Nothing special, it ever worked till ios 8.0 said hello.
The function sendMail sends a mail when a button gets tapped (set via storyboard). I debugged it and the code seems ok, but it crashes with a EXC_BAD_ACCESS code=1 error whenever you're supposed to return back to the main app, like when you tap the send or dismiss button of the MFMailComposeViewController. It seems to me that my View, i mean the view calling the MFMailComposeViewController is deallocated when the MFMailComposeViewController is called, so that when it get dismissed, there's nothing to return on. Some ideas to solve the problem?
[The function didFinishWithResult is never reached: the crash happens before.]
EDIT: To be precise it crashes with bad_access if in the presentViewController i set animated to NO. If it is YES it complain about 'unbalanced calls to begin/end appearance transitions' and tapping send/dismiss does nothing (it not returns. The mail view is alive but tap button does nothing)
EDIT: I am right about the deallocation. He have the same problem but it does not seems to have a valid solution MFMailComposeViewController crash in iOS6 ARC
In my case Arc is turned off and i cannot turn it on for various reasons. The theory is confirmed by zombie instrument. It says 'An Objective-C message was sent to a deallocated 'View' object (zombie) at address: 0x14e01720'
View.h
included MFMailComposeViewControllerDelegate and imported
#import <MessageUI/MFMailComposeViewController.h>
View.m
-(IBAction)sendEmail:(id)sender{
NSString *mailDiretta=emailText.currentTitle;
composer = [[MFMailComposeViewController alloc] init];
[composer setMailComposeDelegate:self];
if ([MFMailComposeViewController canSendMail]) {
[composer setToRecipients:[NSArray arrayWithObjects:mailDiretta, nil]];
[composer setSubject:#"Infos"];
[composer setMessageBody:#"Write to me, dude!" isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:composer animated:YES completion:NULL];
[composer release];
} else
[composer release];
}
// function below is never reached
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"error"
message:[NSString stringWithFormat:#"error %#", [error description]]
delegate:nil cancelButtonTitle:#"dismiss" otherButtonTitles:nil, nil];
[alert show];
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self dismissViewControllerAnimated:YES completion:NULL];
}
}
I would assume it's because you're releasing the composer before it finishes.
[composer release];
EDIT: How is this property initialized and why is it a property? Create it in the method and try. Also, your unbalanced calls are happening because you're animating a UIAlert at the same time you are animating the mail controller dismiss. Each needs to finish prior to prevent that message.
composer = [[MFMailComposeViewController alloc] init];
Try to remove the property and initialize in the function.
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
Make sure you added the delegate properly as well.
#import <MessageUI/MessageUI.h>
#interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate>
Set your delegate like this
composer.mailComposeDelegate = self;
For the unbalanced calls, rearrange your alert like this...
[self dismissViewControllerAnimated:YES completion:NULL];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"error"
message:[NSString stringWithFormat:#"error %#", [error description]]
delegate:nil cancelButtonTitle:#"dismiss" otherButtonTitles:nil, nil];
[alert show];
EDIT 2:
After seeing your comment about not being able to use ARC due to one class I would advice you to simply set a -fno-objc-arc compiler flag on that class and enable ARC across your project and make your life WAY easier.
Disable Automatic Reference Counting for Some Files
I'm calling a method from viewcontroller in an appdelegate. When I was testing functionality I just used NSLog message which works fine (so the connection between viewcontroller and appdelegate is OK). The problem appears once I add a email form into this method. The message I receive is:
Warning: Attempt to present <MFMailComposeViewController: 0x1fdc3990> on <ViewController: 0x1fd9e3b0> whose view is not in the window hierarchy!
Anyone who know what to do? I know there are lot of topics with 'whose view is not in the window hierarchy' issue but none of them helped me.
ViewController.m
...
-(void)mail{
NSLog(#"blablabla");
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:#"Hello and welcome!"];
NSArray *toRecipients = [NSArray arrayWithObject:#"tomas.javnicky#gmail.com"];
[mail setToRecipients:toRecipients];
[mail setCcRecipients:toRecipients];
NSString *emailBody = #"Hey all!";
[mail setMessageBody:emailBody isHTML:NO];
mail.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentViewController:mail animated:YES completion:nil];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"E-mail is not supported on your device"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
switch (result) {
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSaved:
NSLog(#"mail saved");
break;
case MFMailComposeResultSent:
NSLog(#"mail sent");
break;
case MFMailComposeResultFailed:
NSLog(#"mail failed");
break;
}
[self dismissViewControllerAnimated:YES
completion:nil];
}
...
Appdelegate.m
...
-(void)something {
ViewController * vc = [[ViewController alloc] init];
[vc mail];
}
...
This is what solved my problem:
- (void)something {
ViewController *rootViewController = (ViewController*)self.window.rootViewController;
[rootViewController mail];
}
Also check the answer by rmaddy for more info.
Now that you've posted code, the problem is obvious. You create a view controller but you never display it (in the something method). Then you call a method on this undisplayed view controller (mail) which attempts to display the mail view controller from the undisplayed view controller. This is what causes the error.
You need to display the mail controller from a view controller that is already being displayed (such as the rootViewController maybe).
What is the point of your ViewController class?
I have a button at the end of a guide that says Done!I need it to bring up Facebook posting dialogue and also segue back to the menu screen
At the moment I have it opening a Facebook posting screen, which pops up and goes back down when you click post or cancel. I would like it to return to the menu after the facebook process has completed. I have followed a guide on how segue programatically and have added the code to my current postToFacebook IBAction but it didn't work. I then tried to create it's own IBAction and link it to the button but it didnt work either.
Does anyone know how I can get it to segue after the Facebook dialogue
Heres my code for facebook posting in case you need it
- (IBAction)PostToFacebook:(id)sender {
mySLComposerSheet = [[SLComposeViewController alloc] init];
mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[mySLComposerSheet setInitialText:#"I just followed a guide on this App - Get it on the App Store http://"];
[self presentViewController:mySLComposerSheet animated:YES completion:nil];
}
And heres the code for the programatic segue
-(IBAction)nextView{
[self performSegueWithIdentifier:#"next" sender:self]; }
You can put all code in a single -(IBAction) and use a boolean value that changes it's value after executing facebook action.
Something like this,
- (IBAction)PostToFacebook:(id)sender {
if(valueOfBoolean==TRUE){
mySLComposerSheet = [[SLComposeViewController alloc] init];
mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[mySLComposerSheet setInitialText:#"I just followed a guide on this App - Get it on the App Store http://"];
[self presentViewController:mySLComposerSheet animated:YES completion:nil];
valueOfBoolean=FALSE;
}
else{
[self performSegueWithIdentifier:#"next" sender:self];
}
}
Set default value for valueOfBoolean as TRUE in viewDidLoad method.
EDITED :
- (IBAction)facebook:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *facebook = [[SLComposeViewController alloc]init];
facebook = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[facebook setInitialText:[NSString stringWithFormat:#"your string"]];
[self presentViewController:facebook animated:YES completion:nil];
[facebook setCompletionHandler:^(SLComposeViewControllerResult result){
NSString *output;
switch (result) {
case SLComposeViewControllerResultCancelled:
// here you can handle your seque, or your custom action what you want
break;
case SLComposeViewControllerResultDone:
// here you can handle your seque, or your custom action what you want
break;
default:
break;
}
// [self dismissViewControllerAnimated:YES completion:nil];
}];
}
else{
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:#"No Facebook Account" message:#"There are no Facebook accounts configured. You can configure or create accounts in settings ." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alertView show];
}
}
I hope it helps !