I have two issues after usage of MFMailComposeViewController in my application:
After the MFMailComposeViewController is dismissed, the UITextField text on my initial ViewController is cleared
When attempting to display a UIAlertController to indicate a MFMailComposeResult, it fails to display giving a error in the log.
For issue 1: This is my MFMailComposeViewController code. It is an action of a UIAlertController (with UIAlertControllerStyleActionSheet).
UIAlertAction *email = [UIAlertAction
actionWithTitle:#"Email the link"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
// composes new mail message with link
NSString *messageBody = self.link.text;
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setMessageBody:messageBody isHTML:NO];
// customises UI to match application
[[mc navigationBar] setTintColor:[UIColor whiteColor]];
[self presentViewController:mc animated:YES completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self setNeedsStatusBarAppearanceUpdate];
}];
[view dismissViewControllerAnimated:YES completion:nil];
}];
For issue 2: this is my code for displaying an appropriate UIAlertController for each relevant MFMailComposeResult.
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:{
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:#"SearchMe"
message:#"The composition of this email has been cancelled."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *done = [UIAlertAction
actionWithTitle:#"Done"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:done];
[self presentViewController:alert animated:YES completion:nil];
[alert dismissViewControllerAnimated:YES completion:nil];
}
break;
case MFMailComposeResultSaved:{
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:#"SearchMe"
message:#"The composition of this email has saved as a draft."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *done = [UIAlertAction
actionWithTitle:#"Done"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:done];
[self presentViewController:alert animated:YES completion:nil];
[alert dismissViewControllerAnimated:YES completion:nil];
}
break;
case MFMailComposeResultSent:{
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:#"SearchMe"
message:#"The composition of this email has been sent."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *done = [UIAlertAction
actionWithTitle:#"Done"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:done];
[self presentViewController:alert animated:YES completion:nil];
[alert dismissViewControllerAnimated:YES completion:nil];
}
break;
case MFMailComposeResultFailed:
{
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:#"SearchMe"
message:#"The composition of this email has failed. Please try again."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *done = [UIAlertAction
actionWithTitle:#"Done"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:done];
[self presentViewController:alert animated:YES completion:nil];
[alert dismissViewControllerAnimated:YES completion:nil];
}
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
The error given in the log is this:
Warning: Attempt to present <UIAlertController: 0x14ed58b90> on <ViewController: 0x14ee1f7f0> whose view is not in the window hierarchy!
Related
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertController *alert = [[UIAlertView alloc] initWithTitle:#"Alert"
message:#"Are you sure you want to Delete your account ?"
delegate:self
cancelButtonTitle:#"Delete Account"
otherButtonTitles:#"Cancel", nil];
UIAlertAction* ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
//Do Some action here
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"logged_in"];
// alert.tag = 104;
// [alert show];
[self displayAlertForRemoveAccountWithMessage:#"Are you sure you want to Delete your account ?"];
UINavigationController *nav = [self.storyboard instantiateViewControllerWithIdentifier:#"stratingNav"];
[nav setModalPresentationStyle: UIModalPresentationOverFullScreen];
[self presentViewController:nav animated:YES completion:nil];
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)displayAlertForRemoveAccountWithMessage :(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert"
message:message
delegate:self
cancelButtonTitle:#"Delete Account"
otherButtonTitles:#"Cancel", nil];
alert.tag = 103;
[alert show];
}
i am trying to implement delete account function with objective c kindly please tell me what else need to be added in this code..
self.infoView.hidden = NO;
self.infoView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
i want to call thin in table view
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row==0) {
return;
}
NSMutableDictionary *Tag_Dic = [NSMutableDictionary dictionary];
[Tag_Dic setObject:[NSNumber numberWithInteger:indexPath.row] forKey:#"Tags"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"MoveToNext" object:self userInfo:Tag_Dic];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:indexPath.row forKey:#"SenderTag"];
[defaults synchronize];
}
Try this. You have to show alertController when tapped on UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
[cell.button addTarget:self action:#selector(presentAlert) forControlEvents:UIControlEventTouchUpInside];
}
Then write your code for UIAlertController in presentAlert selector.
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Title"
message:#"message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
If you want to show alert when tableview cell is clicked then do following in didSelectRowAtIndexPath method.
For iOS 9 and earlier,
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Message" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Button1",#"Button2", nil];
alertView.delegate = self;
[alertView show];
and user UIAlertView's delegate method to implement your logic when button is clicked
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
For iOS 9 and onwards (UIAlertView is deprecated.)
UIAlertAction *actionOK = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//handel when OK button is pressed.
}];
UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
//handel when Cancel button is pressed.
}];
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:#"Title" message:#"Message" preferredStyle:UIAlertControllerStyleAlert];
[alertVC addAction:actionOK];
[alertVC addAction:actionCancel];
[self presentViewController:alertVC animated:true completion:nil];
In ios 8.3 and earlier work this code,
- (void)saveButton {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
After 8.4 popup action used UIAlertController and i have create the UITextField in popup view and action is give below,
- (void)callAlert {
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:#"Enter Folder Name"
message:#"Keep it short and sweet"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){
//Do Some action here
UITextField *textField = alert.textFields[0];
NSLog(#"text was %#", textField.text);
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
NSLog(#"cancel btn");
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = #"folder name";
textField.keyboardType = UIKeyboardTypeDefault;
}];
[self presentViewController:alert animated:YES completion:nil];
}
Finally call this method where you want, hope its helpful.
i Create two buttons of UIAlertcontroller:
One Button - "OpenCamera"
Two button - "OpenGallery"
I just can not understand how I create action when I click on one of them.
- (IBAction)takePic:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet]; // 1
UIAlertAction *openCamrea = [UIAlertAction actionWithTitle:#"open camrea"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}];
UIAlertAction *openGallery = [UIAlertAction actionWithTitle:#"open gallery"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}];
[alert addAction:openCamrea];
[alert addAction:openGallery];
[self presentViewController:alert animated:YES completion:nil];
}
The handler is the block to be executed on the selection of the item.
UIAlertAction *openGallery = [UIAlertAction
actionWithTitle:#"open gallery"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// Code to run when the open gallery option is pressed.
}];
BTW I think the long unbroken lines in the question really don't help as they effectively hide the key parameter.
The complete code:
- (IBAction)takePic:(id)sender {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *openCamrea = [UIAlertAction actionWithTitle:#"open camrea"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)
{
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"message:#"Device has no camera"delegate:nil cancelButtonTitle:#"OK"otherButtonTitles: nil];
[myAlertView show];
}
else
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
}];
UIAlertAction *openGallery = [UIAlertAction actionWithTitle:#"open gallery"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action)
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}];
[alert addAction:openCamrea];
[alert addAction:openGallery];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.img.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
Put your code inside the handler blocks you are passing to [UIAlertAction actionWithTitle:style:handler:]
For example:
UIAlertAction *openCamrea = [UIAlertAction actionWithTitle:#"open camrea"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
// openCamera action code goes here
}];
UIAlertAction *openGallery = [UIAlertAction actionWithTitle:#"open gallery"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
// openGallery action code goes here
}];
I have problem, my app using default uiactivityviewcontroller, but it too big on iphone 6+. How to fix it ?
Button in my app too big
Button other app
My code
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[self presentViewController:mail animated:YES completion:NULL];
UIAlertController *actionSheet= [UIAlertController
alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *actionSheetDeleteDraft = [UIAlertAction
actionWithTitle:#"Delete Draft"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(#"Delete is pressed");
}];
UIAlertAction *actionSheetSaveDraft = [UIAlertAction
actionWithTitle:#"Save Draft"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
NSLog(#"Save pressed");
}];
UIAlertAction *actionSheetCancel = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
NSLog(#"Cancel pressed");
}];
[actionSheet addAction:actionSheetDeleteDraft];
[actionSheet addAction:actionSheetSaveDraft];
[actionSheet addAction:actionSheetCancel];
[self presentViewController:actionSheet animated:YES completion:nil];
I'm using completionWithItemsHandler to determine if selectedItems were posted to Tumblr. I want to present a 'Success!' alert if the post was complete but completionHandler returns 'completed' even if the user wasn't able to log into Tumblr. That is,user goes through the steps of selecting items, opening activity view, and selecting Tumblr --> this opens the Tumblr app and asks for a log in. If the user presses 'cancel' and goes back to my app, the completionHandler says the activity was 'completed'. Is there any way to determine if post was successful? Any way to test if the user was able to log into the app? Any suggestions for dealing with 'success' alerts when there can be these types of problems?
Here is the completion Handler
activityController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *error){
if (error)
{
//NSError *error;
alertController = [UIAlertController alertControllerWithTitle:#"Error" message:#"Error sharing items" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *errorAction = [UIAlertAction actionWithTitle:NSLocalizedString(#"OK", #"OK action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
NSLog(#"Error sharing items: %#", error);
}];
[alertController addAction:errorAction];
[self presentViewController:alertController animated:YES completion:nil];
}
else if (completed)
{
[self.activityIndicator stopAnimating];
if ([self.giftID isEqualToString:#"general"]||[self.giftEntity.giftThanked isEqualToString:#"YES"])
{
alertController = [UIAlertController alertControllerWithTitle:alertTitle message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(#"OK", #"OK action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
// NSLog(#"OK action");
[self dismissViewControllerAnimated:YES completion:nil];
}];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
if (![self.giftID isEqualToString:#"general"]&&[self.giftEntity.giftThanked isEqualToString:#"NO"])
{
alertController = [UIAlertController alertControllerWithTitle:alertTitle message:#"Mark gift as 'Thanked'?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *yesAction = [UIAlertAction actionWithTitle:NSLocalizedString(#"YES", #"yes action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
self.giftEntity.giftThanked = #"YES";
[self.giftBusObj saveEntities];
[self dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction *noAction = [UIAlertAction actionWithTitle:NSLocalizedString(#"NO", #"no action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
self.giftEntity.giftThanked = #"NO";
[self.giftBusObj saveEntities];
[self dismissViewControllerAnimated:YES completion:nil];
}];
[alertController addAction:noAction];
[alertController addAction:yesAction];
[self presentViewController:alertController animated:YES completion:nil];
}
//Deselect all items in stvc
self.textShare = 0;
self.cardButton.selected = NO;
self.textImageBackground.backgroundColor = [UIColor clearColor];
self.cardImageBackground.backgroundColor = [UIColor clearColor];
[spcvc selectPhotosNone];
[self viewDidLoad];
}
else
{
[self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"activity controller - not 'completed' nor 'error'" );
}
};