4

I have a SFSafariViewController opening at the click of a button inside a UIActionSheet. It has been working fine and is still working fine on all the versions of iOS except iOS 11. Is there something they have changed regarding the SFSafariViewController in iOS 11 or in Xcode 9.0 that might have caused this issue?

UPDATE - So it seems like its Xcode 9.0 that is causing this issue. I have tried running it on different iOS versions and all of them seem to be giving this issue. It used to work fine when I ran it using Xcode 8.3.3, something I don't have anymore :(

Here's the code -

- (void)presentWebView:(NSString *)url { url = [url stringByReplacingOccurrencesOfString:@" " withString:@"+"]; url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *URL = [NSURL URLWithString:url]; if (URL) { if ([SFSafariViewController class] != nil) { SFSafariViewController *sfvc = [[SFSafariViewController alloc] initWithURL:URL]; sfvc.delegate = self; [self.tabBarController presentViewController:sfvc animated:YES completion:nil]; } else { if (![[UIApplication sharedApplication] openURL:URL]) { NSLog(@"%@%@",@"Failed to open url:",[url description]); } } } else { // will have a nice alert displaying soon. } 

}

2
  • 1
    can you show your tried code, ios11 has modified Commented Sep 27, 2017 at 5:27
  • @Anbu.Karthik added the code Commented Sep 27, 2017 at 15:48

6 Answers 6

7

I've managed to fix this in my code. I hope this helps anyone else with a similar problem.

I had the exact same problem as described here. I tried everything above and unfortunately nothing worked.

In my app there were different windows. The fix was to ensure the window that would show SFSafariViewController was 'key' before presenting it. For example:

class MyViewController: UIViewcontroller { func showSafariViewController() { // imagine we have 2 windows, one for 'normal' content (key window) and one for 'other' content. lets say we're showing the 'other' content window, and have hidden the 'normal' window. you can see the 'other' content window in the app, but it won't be the key window! let window = // get the 'other' content window // make sure we make it the key window before presenting safari window.makeKey() // now present safari and celebrate victory by triumphantly slurping on your hot black coffee let mySafariViewController = SFSafariViewController(...) self.present(mySafariViewController ...) } } 

I suspect Apple are searching for a SFSafariViewController instance in the window UIApplication.shared.keyWindow. Perhaps they're adding a child view from somewhere else. In the documentation it states The user's activity and interaction with SFSafariViewController are not visible to your app, so perhaps it's the bug is something related to an added level of security https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller

Sign up to request clarification or add additional context in comments.

3 Comments

This fixed my problem! Thank you! PS: You can easily get the root window by using UIApplication.shared.windows[0] (maybe that'll help someone)
I'm using the method like suggested but getting issue - Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x7fab0d301990>.
@Apple unfortunately i'm not sure what to advise without seeing any code - there could be a few reasons for this that are unrelated to this thread. might be worth starting a new thread? else maybe read this and see if it helps stackoverflow.com/questions/9088465/…
5

I have tried to do it using delay and make view of controller loading.Both are working for me.

Method 1. Using delay.

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { let controller = SFSafariViewController(url: url) controller.modalPresentationStyle = .overFullScreen self.present(controller, animated: true, completion: nil) controller.delegate = self } 

Method 2. Loading view.

 let controller = SFSafariViewController(url: url) let _ = controller.view controller.modalPresentationStyle = .overFullScreen self.present(controller, animated: true, completion: nil) controller.delegate = self 

1 Comment

Method two fixed the issue on iOS 12 with Xcode 11. The issue doesn't show up on iOS 13.
3

Very similar to https://openradar.appspot.com/29108332

To fix it, you can disable the lazy loading of the view:

SFSafariViewController *viewController = [[SFSafariViewController alloc] init...]; (void)viewController.view; ... [controller presentViewController:viewController animated:YES completion:nil]; 

3 Comments

by the way what does this - (void)viewController.view; - do?
Worked for me!!
1

Update

Turns out the old answer didn't work, it just worked since I put breakpoints. If I added a thread sleep seems it worked in XCode9, but that's not the best solution. Anyone have another better solution?

SFSafariViewController *sfcontroller = [[SFSafariViewController alloc] initWithURL:url]; if (@available(iOS 11.0, *)) { [NSThread sleepForTimeInterval:0.5f]; } sfcontroller.delegate = self; [controller presentViewController:sfcontroller animated:NO completion:nil]; 

Old Answer

I have the same issue as genaks and tinkered around with SFViewController.

Seems like this code works for me

SFSafariViewController *sfcontroller = [[SFSafariViewController alloc] initWithURL:url]; if (@available(iOS 11.0, *)) { SFSafariViewControllerConfiguration *config = [[SFSafariViewControllerConfiguration alloc] init]; config.barCollapsingEnabled = NO; sfcontroller = [[SFSafariViewController alloc] initWithURL:url configuration: config]; } else { // Fallback on earlier versions } sfcontroller.delegate = self; [controller presentViewController:sfcontroller animated:YES completion:nil]; 

In ios 11, they introduce SFSafariViewControllerConfiguration, and by default the barCollapsingEnabled is true and it seems the one that causing my blank SafariView. Hope this solves yours too

3 Comments

Works but like you said not a good solution. By the way what's so magical about that 0.5 because I tried reducing it and it didn't work.
And after working once, this has stopped working too. The SafariViewController is still blank
what if I need animation?
0

We had this issue: our URL was https://our-side.com/index.html (an Angular site that would redirect to the /account route). When we removed the index.html, the SFSafariViewController loaded correctly!

Comments

-3

The only thing that has worked so far for me is to make the SafariViewController the rootviewcontroller in the following manner -

 ((XYZAppDelegate *)[UIApplication sharedApplication].delegate).window.rootViewController = self.svc; [((XYZAppDelegate *)[UIApplication sharedApplication].delegate).window makeKeyAndVisible]; 

1 Comment

even if it works - it is totally incorrect to replace rootViewController to show SFSafariViewController only

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.