In iOS 9, why is SFSafariViewController is being pushed instead of presented modally?
Solution 1
Here's a simple way to obtain a vertical modal presentation of a SFSafariViewController
:
let safari = SFSafariViewController(URL: url)
safari.modalPresentationStyle = .overFullScreen
presentViewController(safari, animated: true, completion: nil)
Solution 2
I just had the same issue. Also, the done button work even if you don't set up the delegate. Not sure why it happens. However, I found a workaround: wrapping the safari controller in a navigation controller and hiding the navigation bar.
func openURL(url:NSURL) {
if #available(iOS 9.0, *) {
let safariController = SFSafariViewController(url: url)
safariController.delegate = self
let navigationController = UINavigationController(rootViewController: safariController)
navigationController.setNavigationBarHidden(true, animated: false)
self.present(navigationController, animated: true, completion: nil)
} else {
UIApplication.sharedApplication().openURL(url)
}
}
Solution 3
To use the default modal transition style, you can simply set the transitioning delegate equal to self.
let svc = SFSafariViewController(url: url)
svc.transitioningDelegate = self //use default modal presentation instead of push
present(svc, animated: true, completion: nil)
You'll need to adopt the UIViewControllerTransitioningDelegate
protocol in your view controller, but there are no required functions to implement.
This was mentioned in Session 225 at WWDC, What's New in Safari View Controller.
Solution 4
Objective-C version of iGerms answer:
-(void)openURL:(NSURL *)url {
SFSafariViewController *safariController = [[SFSafariViewController alloc]initWithURL:url];
safariController.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:safariController];
[navigationController setNavigationBarHidden:YES animated:NO];
[self presentViewController:navigationController animated:YES completion:nil];
}
![abc123](https://i.stack.imgur.com/4YhGO.png?s=256&g=1)
abc123
Updated on July 24, 2022Comments
-
abc123 almost 2 years
I'm presenting a
SFSafariViewController
by callingpresentViewController:animated:completion:
on aUIViewController
instance.The result is that it gets pushed on (slides in from the right), as if I called
pushViewController:animated:
on aUINavigationController
instance. I've verified that this is all happening on the main queue. And the presenting view controller is not a modal itself (which shouldn't matter anyways, but just in case, we can rule that out).If I substitute the
SFSafariViewController
with aUIViewController
, it works as expected, it presents modally.weakSelf.oAuthViewController = [[SFSafariViewController alloc] initWithURL:url]; [viewController presentViewController:weakSelf.oAuthViewController animated:YES completion:nil];
Any idea why or how to work around this?
-
Ivan Ičin almost 8 yearsWhile it works better when navigating back, this is not modal.
-
zidanex about 6 yearsiGerms solution is working, but this one is more elegant. Thanks!
-
tadija almost 6 yearsI found that
.overCurrentContext
works better since it also prevents a bug on iPhone X when status bar is hidden (transparent status bar area). -
John Scalo about 5 yearsThis is the only method that works if you're using a custom transitioning delegate. If presenting the
SFSafariViewController
directly, then the transitionContext's from view will always be nil, even with othermodalPresentationStyle
s.