8

SFSafariViewController has this bug that is not reproducible in Safari.

Regularly it will obscure the top of a fixed panel behind the site name / done chrome.

This happens cause internally it loses sync between actual height of the page and size of the shrinking header chrome.

Good small header

correct small header

Bad small header (SF chrome should be small but it is big)

sad

Good large header

correct big header

This issue was reported elsewhere at: https://meta.stackexchange.com/questions/279792/new-ios-chat-headers-occasionally-hide-behind-safari-navigation-controls-when-vi and is an issue in iOS 9 and up (still an issue in 12.0.1)

To reproduce make a dummy app with SFViewController and navigate to a site with a fixed header such as bbs.boingboing.net then click around and browse a few topics.

Since this bug is now a couple of years old I am wondering if there is some sort of workaround that does not involve adding a general padding to the top of the header?

Minimal repro

Make a page with this HTML

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
      body {
        height: 2000px;
        background-color: green;
      }
      header {
        width: 100%;
        height: 50px;
        background-color: red;
        color: white;
        position: fixed;
        top: 0;
      }
    </style>
  </head>
  <body>
    <header>Hello</header>
  </body>
</html>

Open in SafariViewController (host it somewhere online and then email a link, gmail app in iOS uses Safari View Controller, Discourse app as well)

Scroll quickly to the bottom

Half the header is hiding.

Insets make no difference inset for top is 0, cover viewport property makes no diff.

Sam Saffron
  • 128,308
  • 78
  • 326
  • 506

2 Answers2

3

The Issue

Testing in different environments shows that the issue only appears in SFSafariView and the original safari app is not infected. And it only appears in iPhone's with notch in portrait mode when user reaches the end of the page and scrolls again; So the page should go up and navigation bar automatically appears again and conflict will happen.

iPhone 8 iPhone 8 - Bottom of the page - Portrait (OK)

iPhone XR - Portrait iPhone XR - Bottom of the page - Portrait (NOT OK)

iPhone XR - Landscape iPhone XR - Bottom of the page - Portrait (OK)

iPad Pro 9.7 - Landscape iPad Pro 9.7 - Bottom of the page - Landscape (OK)

In some cases this may not be SFSafariViewController's bug.

  • So if you have access to front-end developers of the site that you want to embed in the SFSafariViewController, introduce the following to them:

  • Safe Area Inset

Therefore to resolve this Apple implemented new safe-area-inset, pre-defined set of 4 constants and a new CSS function called constant(). The safe area pre-defined constants are as follows: safe-area-inset-top, safe-area-inset-right, safe-area-inset-bottom and save-area-inset-left. When you combine all four of those constants, you can reference the current size of safe area inset on each side. The constant() works everywhere a var() does.

There are a bunch of sites that show you how to adopt a web page to iPhone X. Here's one of them.

Maybe they could try placing the div outside of the scrollable part, and have the position fixed. So if you have a code where it scrolls:

<div id="scroll-container">
  <div id="scrollable">
  </div>
<div>

Such where any element in the div scroll-container, it will scroll.

If they place it outside of the scrollable part:

<div id="scroll-container">
<div>
<div id="not-scrollable">
</div>

and put position:fixed; or position:absolute; or position: sticky or device-fixed; or etc. in the css for #not-scrollable, It shouldn't scroll.

  • So if you don't have access to front-end developers of the site that you want to embed in the SFSafariViewController try the following (Not recommended):

  • Try turning barCollapsing safariViewController.configuration.barCollapsingEnabled = false

  • or Try embedding it in a navigationController and get rid of the SFView's header

  • or Use Implement a full screen WKWebView with controller instead of SFSafariViewController.

Note (For those who mess with the toolbar)

  • You can use the delegate methods to determine the loading and loaded state of the web page and enable/disable it to get round the page layout initialization bug. (You can use manual delay too)
  • You can use private APIs to hide or show the bottom toolbar. But it's not preferred and it will reject from apple appstore.
danronmoon
  • 3,814
  • 5
  • 34
  • 56
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • I appreciate the thoughtful reply here but you are missing the root bug here... adding this does not make any difference. .d-header { top: constant(safe-area-inset-top); } From the panels perspective `safe-area-inset-top` is 0 and it thinks the whole page is being rendered in plain view, this all works 100% fine in Safari. In Safari View Controller, sometimes, position 0 is behind the URL bar. barCollapsingEnabled=false will work around this issue but then the footer overlay will always be there which is a shame. – Sam Saffron Oct 23 '18 at 03:04
  • 2
    I worked in many startups and every time we face this problem, the front-end team made it with a little changes in the CSS or other files related to layout @SamSaffron about the footer view, yes, this is just a work around and you can extend it. I'll update the answer for it and you can check it out and upvote if you find the answer useful ;) – Mojtaba Hosseini Oct 23 '18 at 07:10
  • Note: barCollapsingEnabled = false breaks things 100% consistently so I don't think it is a feasible solution. Only feasibly solution I can think of is stop trying position fixed panels on the top or bottom of a page. everything else I tried breaks in SVC. – Sam Saffron Oct 24 '18 at 07:01
  • Updated the OP with a minimal repro, sadly non of the suggestion in the reply help any. Hacking scrolling is going to be very risky. – Sam Saffron Oct 24 '18 at 07:52
  • It's very difficult to reproduce the state of the bug. But I'm working on it. @SamSaffron – Mojtaba Hosseini Oct 24 '18 at 10:20
  • @SamSaffron Since understanding the issue is 50% the solution, I added my test results to answer and limit the issue scope. Please check it out and tell me your thoughts. – Mojtaba Hosseini Oct 24 '18 at 20:51
  • I think you have the scope more or less right here, only seen it on "notch" phones in portrait, I will assign you the bounty if nothing new pops up, not this can also happen in regular use of a site its just that this is the simplest way to get a 100% consistent repro. – Sam Saffron Oct 25 '18 at 20:22
  • I gave you the bounty but the answer should be corrected this this a legitimate bug in safari view controller. – Sam Saffron Oct 27 '18 at 07:55
  • Yes it is absolutely a bug and apple fixed it in the original safari app. But I'll continue investigate about how to round this and let you know if I find any updates. Tnx @SamSaffron – Mojtaba Hosseini Oct 27 '18 at 07:59
  • 1
    understood, but we can't really have this answer start with "Actually it's not a SFSafaryViewController's bug." it is confusing, can you edit this – Sam Saffron Oct 28 '18 at 21:48
0

What if you override the prefersStatusBarHidden as below ?

override func prefersStatusBarHidden() -> Bool {
    return true
}

And you may want to add a reload button manually :-(

PrathapG
  • 751
  • 1
  • 7
  • 21