Issue when using MFMailComposeViewController - ios

I have a tricky problem. In one of my app, with over 150.000 downloads... I have a problem which seldom occurs and which I can't seem to figure out.
The problem is the following:
In a view where the user can share a list via email, I open the mail window using MFMailComposeViewController. However, in some few cases the app seems to get a problem using the mail composer. The user presses the share button, the mail windows slides up, waits about 1-2 sec and then closes again. No content in the mail window, although I do send data to it.
I myself have not been able to re-create the problem on any device or in the simulator, however one colleague has.
I ran the app using XCode on his phone and got the following in the logs:
2013-03-01 14:43:39.604 appname[318:907] <MFMailComposeRemoteViewController: 0x1ebfb100> timed out waiting for fence barrier from com.apple.MailCompositionService
2013-03-01 14:43:39.631 appname[318:907] viewServiceDidTerminateWithError: Error Domain=XPCObjectsErrorDomain Code=2 "The operation couldn’t be completed. (XPCObjectsErrorDomain error 2.)"
I googled the error "timed out waiting for fence barrier from com.apple.MailCompositionService" but can't really find any help.
Does anybody have any experience with this? How can I solve it?
My code for opening the view:
-(void)displayComposerSheetWithBodyString:(NSString *)aBody
{
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc]init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Lista"];
NSString *emailBody = aBody;
[picker setMessageBody:emailBody isHTML:NO];
[self.navigationController presentModalViewController:picker animated:YES];
}
else
{
[[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"Din enhet är inte redo att skicka e-post. Kontrollera dina inställningar", nil)
message:nil
delegate:self
cancelButtonTitle:NSLocalizedString(#"OK", nil)
otherButtonTitles:nil]
show];
}
}

Not sure if you have fixed the problem, but I have met it recently in my project.
A workaround I did was to allocate and initiate MFMailComposeViewController in an earlier stage, and hold it in one static variable, whenever it's needed, get the static MFMailComposeViewController instance and present it.
It seems working for me, hope it will work for you, too.

a had the same issue, and this fixe helped me:
https://twitter.com/christian_beer/statuses/321295533077565440
"#nathangaskin well… that was long ago :) But if I remember correctly, it worked after I removed the custom fonts from my UIAppearance code"
It works fine for me.
Also, second option is to simply wrap displaying call into
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
block

I have exactly the same issue. I think I have nailed it down to the time it takes to formulate the message body string.
Content from comment
//Message Body
NSString *msgBody = [NSString stringWithFormat:
#"I noticed these results in pocketKPI. The %# was at %# which is a variance of %#(or %#) to the target defined as %#. When you have some time let's discuss.",
self.itemToView.kpiName,
[DFSKpiFormatter formatNumberAsString:self.itemToView.currentValue], [self.itemToView determineVarianceLabelText],
[self.itemToView determineVariancePercentLabelText],
[DFSKpiFormatter formatNumberAsString:self.itemToView.targetValue]];

Related

iOS Document Sharing: "Save to Dropbox" always fails

Posting after finding answer
After "rubber duck debugging" this answer a bunch, I finally came across the correct answer on a question that appears to me to be unrelated. I think this question (and its answer) are still relevant, so I'm posting the question and will post my own answer to hopefully help others like me.
I am creating a PDF in my iOS app that I would like to allow the user to export. For the purposes of this testing, I'm trying to save it to my personal Dropbox on a physical device.
I have turned on iTunes file sharing, and I can verify that the PDF file is being generated correctly, and when I copy it off of my device (iPad Pro Gen. 2 running iOS 11), I can open the PDF and it has the expected content and appearance.
I am able to get the document pop-up to display correctly, and I have options to share via:
Line 1: AirDrop
Line 2: Message, Mail, Add to Notes, (Facebook) Messenger, etc.
Line 3: Copy, Print, Save to Files, Save to Dropbox, etc.
No matter what I try to select (Save to Dropbox is the one I want to solve, but the issue seems universal), it fails. Of note, when I click Save to Dropbox, I do see the Dropbox panel display, but there is immediately a modal over top of the Save to Dropbox modal that says, "An unknown error occurred."
I have tried to look around and see how to get more information about this error, but I'm stumped. I'm not sure if it's correlated, but I get this message in the console:
[AXRun-PID] Client requesting unsuspension of PID:813 Name:<redacted>
Trying to google that error has proved unfruitful.
Here's the code where I generate the PDF and show the menu:
#pragma mark • Sharing Methods
- (void)showShareMenu {
NSArray *bookList = [BookManager bookList];
NSURL *pdfUrl = [PdfGenerator generatePdfFromBooks:bookList];
UIDocumentInteractionController *vc = [[UIDocumentInteractionController alloc] init];
vc.name = #"Booklet.pdf";
vc.URL = pdfUrl;
vc.UTI = #"com.adobe.pdf";
[vc presentOptionsMenuFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];
}
I've tried using UIDocumentInteractionController *vc = [UIDocumentInteractionController interactionControllerWithURL:pdfUrl]; instead of the one above, but the results are the same.
I tried making self the delegate of vc and then tried to implement the following methods:
- (void)documentInteractionController:(UIDocumentInteractionController *)controller
willBeginSendingToApplication:(nullable NSString *)application;
- (void)documentInteractionController:(UIDocumentInteractionController *)controller
didEndSendingToApplication:(nullable NSString *)application;
Neither of those methods ever fired.
Interestingly, though I think I've supplied the file name correctly based on what I've read, the name in the File textbook in the Save to Dropbox modal is a current timestamp (e.g., File Oct 28, 11 12 22 PM). The Dropbox modal stays up until I click "OK" on the "An unknown error occurred" modal, and then disappears immediately.
It seems like I'm somehow not providing the right information, but I'm not sure how. It seems like there ought to be a delegate method to indicate an error to me, but I don't see anything like that in the docs. (It is late, and I have been looking at this for hours, including reading several related tutorials, so I could have missed something obvious.)
I came across this answer as an example question while asking this current question.
It doesn't really ask the same question I have, nor did that user have the same error outputs I did. But, the linked answer did work for me, too.
The problem I had in the code above was that I was not keeping the UIDocumentInteractionController around after I created it. Adding a private property fixed this issue. So, the following code now works:
#pragma mark • Sharing Methods
- (void)showShareMenu {
NSArray *bookList = [BookManager bookList];
NSURL *pdfUrl = [PdfGenerator generatePdfFromBooks:bookList];
self.docController = [UIDocumentInteractionController interactionControllerWithURL:pdfUrl];
self.docController.name = #"Booklet.pdf";
self.docController.UTI = #"com.adobe.pdf";
[self.docController presentOptionsMenuFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];
}

productsRequest seems to return empty set for one app while non-empty for another

dear all:
I inherited a program that can be compiled to two iOS apps, one for traditional Chinese and one for simplified Chinese.
The apps have inAppPurchase and worked fine in the last version.
Then this year, I revised the program without changing the inAppPurchase process.
But after the submissions, apple rejected the traditional Chinese app saying that it would be stuck in the inAppPurchase page.
But the simplified Chinese app was approved.
I then traced the program to the following code.
It seems that my apps always get the empty response set for productsRequest.
However, I must say that I did not do sandbox testing since I don't know how.
I am not sure why it worked fine in last year's version but failed in this year's.
Is there change to some default assumption on bundle id, application id, .. etc.
I checked all my program and could not find where I can set up the app id for the productsRequest statement.
My program is just standard as follows.
Any help will be appreciated.
// determine whether payments can be made
if (![SKPaymentQueue canMakePayments]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"warning" message:#"ineffective" delegate:nil cancelButtonTitle:#"OK?" otherButtonTitles:nil];
[alert show];
}
else {
[buttonPrice setTitle:#"waiting for price" forState:UIControlStateNormal];
[buttonPriceAll setTitle:#"waiting for price" forState:UIControlStateNormal];
// Request product data
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:bookProductIds[0], bookProductIds[purchaseVolume-1], nil]];
productsRequest.delegate = self;
[productsRequest start];
[self operationStarted];
}

_UIViewServiceInterfaceErrorDomain

I'm having a problem with MFMailComposeViewController
I'm getting this error
viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "The operation couldn’t be completed. (_UIViewServiceInterfaceErrorDomain error 3.)" UserInfo=... {Message=Service Connection Interrupted}
with this code
- (IBAction) mailbutton:(id)sender
{
if([MFMailComposeViewController canSendMail])
{
[MSAPP.globalMailComposer setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentViewController:MSAPP.globalMailComposer animated:YES completion:nil];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to mail. No email on this device?"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[MSAPP cycleTheGlobalMailComposer];
}
}
This is a known issue with the iOS 8 simulator. Please see this post for a possible workaround.
You MUST allocate and initiate MFMailComposeViewController in an
earlier stage, and hold it in one static variable, whenever it's
needed, get the static MFMailComposeViewController instance and
present it.
AND you will almost certainly have to "cycle" the global
MFMailComposeViewController after each use. It is not reliable to
"re-use" the same one. Have a global routine which release and then
re-initializes the singleton MFMailComposeViewController. Call it each
time after you are finished with it
Credit goes to "Joe Blow" for the post. Judging by your code, you have already declared global mail composer. Try "recycling" it as the post suggests to see if that solves your problem. I am having the same issue and unfortunately this solution doesn't fix mine. I can confirm this solution works on the iOS 7.1 simulator but not iOS 8, although it has been suggested it will work on a physical iOS 8 device.

Observe NSLog messages in Xcode

I'm debugging a 3rd party SDK which puts lot of useful information into the console.
I used to display some messages in tooltips (for our tester), which I'm receiving from SDK delegate.
But delegate methods don't include many details and sometimes it turns helpless, otherwise console includes much more helpful information (especially if the SDK's log level is set to DEBUG_ALL or something like that).
So, my question - is it possible to observe NSLog messages and to be notified in some way when they are printed to console? Of course I would like to have string message as a parameter?
I would like to display it on device/simulator screen, so that the tester doesn't have to run XCode or view the device's console.
I'm using iConsole for the same purpose. It's quite useful.
What SDK? If the SDK supports CocoaLumberjack, then I suggest installing that, and configuring the loggers to do what you want -- even route somewhere else.
CocoaLumberjack gives you a lot of power and configurability when it comes to logging.
If your SDK uses NSLog to print the details in the console, then you can use macros to redefine the NSLog.
#define NSLog(FORMAT, ...) ShowLogInAlert(FORMAT);
void ShowLogInAlert(NSString *format, ...){
//show the log in the alert here.
va_list ap;
va_start (ap, format);
format = [format stringByAppendingString:#"\n"];
NSString *msg = [[NSString alloc] initWithFormat:[NSString stringWithFormat:#"%#",format] arguments:ap];
// NSLog(#"%#", msg);
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:msg message:#"" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
va_end (ap);
}

MFMailComposeViewController large Video attachment failed to send

I am sending video file as an mail attachment, when i send small video then every thing is work perfect and mail has sent, but when video size is large the it give memory warning several time and unable to sent the mail. I am allocating memory for NSdata and releasing it properly. Please give your valuable suggestion. Thanks in advance
Here is my code
MFMailComposeViewController *picker1 = [[MFMailComposeViewController alloc] init];
picker1.mailComposeDelegate = self;
[picker1 setSubject:#"AKR Video"];
NSData *videoData=[[NSData alloc] initWithContentsOfFile:self.path ];
[picker1 addAttachmentData:videoData mimeType:#"video/MOV" fileName:#"Video.MOV"];
[videoData release];
[self presentModalViewController:picker1 animated:YES];
[picker1 release];
Loading a 15 MB anything into RAM on a pre-2009 iPhone or iPod is going to really push the limits of your process's available memory, so it's not surprising there's a cap. I wouldn't try to convince the compose view to accept a larger attachment; instead, I'd suggest you transfer the file to some external server and either e-mail a link to it or send the mail from there.(+1)

Resources