Warning: Attempt to present on whose view is not in the window hierarchy!
Yes I have looked at the other questions and answers before posting this question. They have not helped me resolve this. Here's what I am doing. I am calling on my singleton class socialHelper to display an action sheet, where postToFacebook
method is an option to select. When clicking on this action, I get the Warning above and the postToFacebook
is not displayed. I'm calling this from a UIViewController with the UINavigationController
as the main controller, and my SocialHelper class is a NSOject
.
- (void)postToFacebook
{
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[slComposeViewController setInitialText:@"Building stairs? Checkout StairsPro on the app store!"];
[slComposeViewController addImage:[UIImage imageNamed:@"StairsIcon120x120.png"]];
[slComposeViewController addURL:[NSURL URLWithString:@"https://itunes.apple.com/us/app/stairs-pro/id477032819?ls=1&mt=8"]];
[self presentViewController:slComposeViewController animated:YES completion:nil];
// I've also tried this, which shows the post window, but after hitting cancel or post, my previous viewController is not the current viewController. So my navigation bar is gone and can't move around in my app.
// [[[[UIApplication sharedApplication]delegate]window]setRootViewController:slComposeViewController];
}else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"No Facebook Account" message:@"No Facebook account has been configured. You can configure or create a Facebook account in settings." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
[alert show];
}
}
So what I'm asking is what is the best way to get the slComposerViewController
to display in this case, also how we could use the UIApplication
option as well. Thank you!
I would change the method to pass in the ViewController to make sure the correct VC is presenting it like so:
- (void)postToFacebookFromVC:(UIViewController*) presentingVC
And inside that method when calling presentViewController use:
[presentingVC presentViewController:slComposeViewController animated:YES completion:nil];
I assume then that using your socialHelper singleton class would be something like:
[[socialHelper sharedResource] postToFacebookFromVC:self]; //inside the VC that you want to display it
For your second question on using the rootViewController try this:
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:slComposeViewController animated:YES completion:nil];
Edit: Since the first two suggestions didn't work for your project, try getting the topMost ViewController and presenting slComposeViewController from it instead of "self" like so:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
[topController presentViewController:slComposeViewController animated:YES completion:nil];
This answer won't resolve your issue but it should make some sense of why it isn't working and help you towards finding the right solution for what you originally intended.
SLComposeViewController
being a UIViewController
has an associated UIView
that will be displayed on top of the view of the controller receiving the message presentViewController
.
As correctly done in this line but, self
needs to be a UIViewController
(an object that has a view property).
[self presentViewController:slComposeViewController animated:YES completion:nil];
It will work if you move your -postToFaceBook
method out of the SocialHelper
class and put it inside your UIViewController
class (file) that will display the action sheet, so that way self
is actually a UIViewController
instead of NSObject
.
From Apple's UIViewController reference page:
When you call the presentViewController method on a UIViewController it sets the presentedViewController property to the specified view controller, resizes that view controller’s view and then adds the view to the view hierarchy.
Your SocialHelper
class is not a view controller so it does not have a view to which the action sheet view could be added to display it (on top).
I'm thinking even if you inherit your SocialHelper
from UIViewController
, the view of your SocialHelper
would not be in your controller's view hierarchy.
If it is only two or three view controllers where you need to display the action sheet, I would replicate the code instead of creating a separate class; if it is several view controllers, then it makes sense to have the action sheet display logic as a separate class, you just need to find the right design pattern to do that.
Edit 1
Forgot to mention the declaration of your variable is missing the SLComposeViewController *
Is it just missing in your post or you have declared the variable somewhere else in your viewcontroller class?
Try declaring it right there in the same line you create the SLComposeViewController
; that might fix the issue. If that did not work then double-check all you need to do to support Facebook in your app by looking at this very simple and easy to follow tutorial.
SLComposeViewController *slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
I'm assuming you created your navigation controller with main view controller as its root:
navigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
And to show the flip side controller you do this in your main view controller:
[[self navigationController] pushViewController:flipSideViewController animated:NO];
The flip side controller has the about button to show the about view when tapped; I'm thinking you do a presentViewController not a push:
[self presentViewController:aboutViewController animated:YES];
Finally, in the about view controller you should have your -postToFacebook method with the corrected line mentioned above; which will be called by the log (button?).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With