I have a MFMessageComposeController, and I want to send images via iMessage (SMS not available on my iPad).
This is my code:
- (void)presentMessageController {
if(![MFMessageComposeViewController canSendAttachments])
{
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Your device doesn't support sharing photos via SMS!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[warningAlert show];
return;
}
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
[messageController addAttachmentData:imgData typeIdentifier:(NSString *)kUTTypePNG filename:#"image.png"];
// Present message view controller on screen
[self presentViewController:messageController animated:YES completion:nil];
}
The problem seems to be in [messageController addAttachmentData...]. The messageController is not presented, instead a blank screen appears, and app is hanging up, and after 1-2seconds, the delegate responds with MessageComposeResultCancelled, and I see this in console:
timed out waiting for fence barrier from com.apple.mobilesms.compose
Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!
If I comment that line, the messageController is presented (iMessage is opened).
IMPORTANT:
This is happening when testing on iPad (I tested on iPad 2 only, with iOS 7.0.3 installed). Same code works perfect in iPhone 5, 4, 4S with iOS 7.0.3.
When black screen appears, there is no way to return to app. You have to terminate the app, and restart.
Anybody experiencing same issue? Please help. Thanks.
try changing:
[messageController addAttachmentData:imgData typeIdentifier:(NSString *)kUTTypePNG filename:#"image.png"];
to:
[messageController addAttachmentData:imgData typeIdentifier:#"public.data" fileName:#"image.png"];
Call presentMessageController method after some delay
[self performSelector:#selector(presentMessageController) withObject:nil afterDelay:0.5];
Related
I'm a bit dazzled here. And I do think it might be something stupid, but here it goes.
I'm using ABPadLockScreen to set a password and it works just fine when I open the app first time and if the app is closed (terminated) and reopened, but if I just go home and return to it I get the following warning
Warning: Attempt to present <ABPadLockScreenViewController: 0x7fdc70f1d5a0> on <ViewController: 0x7fdc70f18e00> whose view is not in the window hierarchy!
Just for more information here is the code that triggers it, it's inside the viewDidAppear
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
if (!self.pin && delegate.terminated) {
// [[[UIAlertView alloc] initWithTitle:#"No Pin" message:#"Please Set a pin before trying to unlock" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
//return;
[self dismissViewControllerAnimated:YES completion:nil];
} else if (!self.isPin && !delegate.terminated) {
ABPadLockScreenViewController *lockScreen = [[ABPadLockScreenViewController alloc] initWithDelegate:self complexPin:YES];
[lockScreen setAllowedAttempts:3];
lockScreen.modalPresentationStyle = UIModalPresentationFullScreen;
lockScreen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:lockScreen animated:YES completion:nil];
}
If you're wondering about the delegate, it was so the Password Screen would show up when the app was simply closed and reopened and that's when the warning occurs.
Also, if I simply switch from one view to another, the damn thing shows up again.
Thanks in advance
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 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.
I've got a MFMailComposeViewController and I believe it is implemented correctly. However when it is displayed on the screen (through modal) it just opens, hangs for a second, then closes and logs MFMailComposeResultCancelled
any thoughts?
if ([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
if( composer == nil ){
UIAlertView* alert_view = [[UIAlertView alloc] initWithTitle:#"message"
message:#"You will need to setup a mail account on your device before you can send mail!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert_view show];
return;
}else{
composer.mailComposeDelegate = self;
[composer setSubject:#"I have an issue"];
[composer setMessageBody:#"" isHTML:NO];
[composer setToRecipients:#[#"email"]];
}
[self presentViewController:composer animated:YES completion:^{
;
}];
EDIT found these in the log
Unbalanced calls to begin/end appearance transitions for <UINavigationController: 0xcda5e90>.
The operation couldn’t be completed. (Cocoa error 4097.)
MFMailComposeResultCancelled is called if you have any changes that occur to the UI when the MFMailComposer is pulled up.
I must be the default iOS Navigation header, though you can change the tint.
On your completion if you don't do anything, put nil, probably this is the problem.
I am trying access the Photo Library from an iPad application. It is said that "On iPad, UIImagePickerController must be presented via UIPopoverController". That's exactly the log message that I get too.
Here is a snapshot of my app:
Since I am already listing the options via a popover, it doesn't make sense to go another popover from within. The accessPhotoLibrary method gets called when the user taps on the "Photo Library" cell.
-(void)accessPhotoLibrary{
NSLog(#"Photo library access requested!");
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
NSLog(#"Photo Library");
[imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[imagePickerController setDelegate:self];
[imagePickerController setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:imagePickerController animated:YES completion:nil];
}
else{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Photo Library"
message: #"Sorry, couldn't open your photos library"
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
But how do I get around this problem of having to access the photo library using a popover when I am using one already??
Any help is much appreciated.
You can present the image picker within the same popover. Hold a reference to the popover (the parent view controller presenting the popover can pass a reference) and then you can do the following:
[_parentPopover setContentViewController:imagePickerController animated:YES];
If needed, you can change the size of the content presented in the popover using the property "contentSizeForViewInPopover" in the image picker view controller.