Presenting view controllers on detached view controllers is discouraged in iOS 8 - ios

I want to attach pdf to the mail but I am getting following error when i run in iOS 8. when i open activity
Presenting view controllers on detached view controllers is discouraged.
When i click on mail, i am getting
Warning: Attempt to present <MFMailComposeViewController:> on <> whose view is not in the window hierarchy!
I am using the following code to do so,
activityVC = [[UIActivityViewController alloc]initWithActivityItems:PDFDataArray applicationActivities:nil];
_popup = [[UIPopoverController alloc] initWithContentViewController:activityVC];
[_popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Not displaying a window.

This is happening because your UIPopoverController is not yet presented and still not a part of the window hierarchy.
The correct way to presnt UIActivityViewController is as follows:
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:PDFDataArray applicationActivities:nil];
if ([activityVC respondsToSelector:#selector(popoverPresentationController)] ) {
activityVC.popoverPresentationController.sourceView = myButton;
}
[self presentViewController:activityVC animated:YES completion:nil];
No need of a UIPopoverController

Related

UIActivityViewController on iPad dismissing "modal view" in iOS 8

I have this wired problem with UIActivityViewController on iPad when dismissing it.
What I have is a MainViewController from which I present a view controller like so (modal view):
ReaderViewController *readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
[self presentViewController:self.readerViewController animated:YES completion:nil];
In the ReaderViewController's toolbar I have a UIButton to show UIActivityViewController for PDF sharing.
This is how I present the UIActivityViewController:
_activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[document.fileURL] applicationActivities:nil];
UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:_activityViewController];
[popup presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
When UIActivityViewController is presented it works as expected. It will dismiss if I press anywhere on the screen, also as expected. The problem is if I double tap somewhere on the screen, both the UIActivityViewController and ReaderViewController will be dismissed at the same time.
Now, I want only UIActivityViewController to be dismissed not ReaderViewController.
Any solution for this ?
/Cheers
There is a way, declare UIPopoverController *popup as a global variable or property.

How to dismiss a modal view controller, then immediately have the presenting view controller present a different modal view controller?

I'm using an IIViewDeckController as my root view controller. It's a library that allows me to have a sliding menu view controller similar to the sliding menu in the facebook application. It works by initiating it with a center and left view controller and then setting the entire thing as the root view controller. Here's what that looks like in AppDelegate.m:
FeedViewController* mainFeed = [[FeedViewController alloc] init];
UINavigationController* mainStack = [[UINavigationController alloc] initWithRootViewController:mainFeed];
MenuViewController* sideMenu = [[MenuViewController alloc] init];
IIViewDeckController* viewDeck = [[IIViewDeckController alloc] initWithCenterViewController:mainStack leftViewController:sideMenu];
self.window.rootViewController = viewDeck;
When in the center view controller (navStack), I have a button, that when pressed, presents a modal view controller, login:
- (void)openLogin{
LoginViewController* login = [[LoginViewController alloc] init];
[self presentViewController:login animated:YES completion:nil];
}
In login, after the user enters their credentials and logs in, I try to have the navStack dismiss login, and then immediately push in a different controller creator:
- (void)dismissLoginController{
//get a reference to the mainFeed
IIViewDeckController* viewDeck = (IIViewDeckController*)self.presentingViewController;
UINavigationController* navStack = (UINavigationController*)viewDeck.centerController;
FeedViewController* mainFeed = (FeedViewController*)navStack.topViewController;
//have it dismiss login, then push creator
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
[mainFeed openListingCreator];
}
openListingCreator in mainFeed:
- (void)openListingCreator{
ListingCreatorViewController* creator = [[ListingCreatorViewController alloc] init];
UINavigationController* creationStack = [[UINavigationController alloc] initWithRootViewController:creator];
[self presentViewController:creationStack animated:YES completion:nil];
}
The error i'm getting is: Warning: Attempt to present <UINavigationController: 0xa40c790> on <IIViewDeckController: 0xa843000> whose view is not in the window hierarchy!
I'm assuming this is because IIViewDeckController isn't on the screen when I ask it to present a view controller. However openListingCreator is being called AFTER i dismiss the login view controller, so I'm not sure why it's doing this. I believe it has something to do with IIViewDeckController since I have done this same exact process before in other projects without it and had no problems.
Any ideas?
you get this error because the openListingCreator is being called while the transition effect of the LoginViewController is still active. You could put the [mainFeed openListingCreator]; in the completion block of [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; or present creationStack directly from the LoginViewController.
[self.presentingViewController dismissViewControllerAnimated:YES completion:^{
[mainFeed openListingCreator];
}];

Why UIActivityViewController doesn't dismiss MFMailComposeViewController when the presenter is a UITabbarController child?

I have a very simple case where a button shows an UIActivityViewController to share some content. The problem is that the mail composer is not dismissed when the user cancel or sends email.
NSArray *items = [NSArray arrayWithObjects:#"share",nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
I tried to dismiss the modal view in the activityViewController.completionHandler but then the console says that another animation is in process and sometimes crash the app, so this isn't the solution. Besides other social networks work well (facebook, twitter) without doing anything.
After some tests I detected that this only occurs if the UIViewController that presents the UIActivityViewController is a child of a UITabBarController.
If in my AppDelegate I create the app like this it doesn't work:
UIViewController > UINavigationController > UITabbarController > Window
but if I remove the tabbar all works fine!:
UIViewController > UINavigationController > Window
A workaround that solves the problem is presenting from the rootviewcontroller.
[self.view.window.rootViewController presentViewController:activityViewController animated:YES completion:NULL];
but I want to know what's happening here.
Thanks! ;)
I had the same issue and after figuring out I get to know that when we don't present mail composer from the class which is currently active on window , it will fail to take responses some time like it will not get even present on every call, same is the problem with dismisal.
It is not that it is only the case with UITabbarController. It can happen to any architecture when you are presenting it from different controller which is not currently on window. That is why your workaround is working and its not wrong though.
I was presenting mail composer from a button tapped inside uipopover. Mail composer was being presented in that popover controller class. And I was facing the same issue you are facing. Then I changed my code to :
MFMailComposeViewController *mailComposer = [MFMailComposeViewController new];
[mailComposer addAttachmentData:data mimeType:#"application/pdf" fileName:model.documentTitle];
[mailComposer setSubject:model.documentTitle]; // Use the document file name for the subject
if(kBccEmailID)
[mailComposer setBccRecipients:[[NSArray alloc]initWithObjects:kBccEmailID, nil ]];
mailComposer.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
mailComposer.modalPresentationStyle = UIModalPresentationFormSheet;
AppDelegate *delagate =(AppDelegate *) [[UIApplication sharedApplication]delegate];
mailComposer.mailComposeDelegate = [[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject]; // Set the delegate
[(UIViewController *)[[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject] presentViewController:mailComposer animated:YES completion:nil];
[(UIViewController *)[[(UINavigationController *)delagate.window.rootViewController viewControllers] lastObject] is an alternative for your 'self.view.window.rootViewController'.

Present a FormSheet QLPreVIewController within a UIVIewController?

i want to open QLPreVIewController as a from sheet model style.
Here is my code
-(void)openPdfFile{
QLPreviewController *previewer = [[QLPreviewController alloc] init];
[previewer setModalPresentationStyle:UIModalPresentationFormSheet];
[previewer setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
// Set data source
[previewer setDataSource:self];
[previewer setDelegate:self];
// Which item to preview
[previewer setHidesBottomBarWhenPushed:TRUE];
[[[[UIApplication sharedApplication]keyWindow]rootViewController]presentModalViewController:previewer animated:TRUE];
}
but it always present with full screen
help please
From the docs:
You can push it into view using a UINavigationController object, or can present it modally, full screen
So, you could try presenting a navigation controller as a form sheet and pushing the preview controller as the root view controller.

How to show quick look of a document in a splitview based iPad app

I have to show quick look of a document in the detailView of a splitview based app. In the master view I have a UITableView with the list of all the files in the Document folder of my app. I'm trying to use the QLPreviewController in the DetailViewController, in this way:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
previewController.currentPreviewItemIndex = ...;
[[self navigationController] pushViewController:previewController animated:YES];
[previewController release];
I'm able to see the preview of the document, but I don't longer see the toolbar at the top of the detail view, and in portrait mode I'm stuck forever, because I'm not able to see the file list in the master view. I also tried to make DetailViewController subclass of QLPreviewController, but without success.
I think instead of pushing the previewController into the [self navigationController], what I believe you need to do instead, from what you described, is to set the previewController as the detail view of your UISplitViewController.
This can be done like so
[splitViewController setViewControllers:[NSArray arrayWithObjects:masterViewController, previewController, nil]];
If you want to have the navigation bar for for the previewController to appear, you can wrap the previewController with a UINavigationController before setting it as the detail view in UISplitViewController like so:
UINavigationController *wrapperNavigationController = [[[UINavigationController alloc] initWithRootViewController:previewController] autorelease];
[splitViewController setViewControllers:[NSArray arrayWithObjects:masterViewController, wrapperNavigationController, nil]];
Cheers
Try
[self presentModalViewController:preview animated:YES];
instead of
[[self navigationController] pushViewController:previewController animated:YES];

Resources