TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: 100 Day/UIKit/Day 26 Part 4, Challenge 1 &2 included, WKWebView issue/question

Forums > Swift

The initial load of the webView works as advertised, yet any subsequent webView page load overruns the Navigation Bar regardless of website (a couple added and order moved around) or Simulator device selected. I've run through every option available in the IB Attributes Inspector for the Navigation Bar with no effect on the overrun. In all other aspects the program is running correctly, all buttons, function calls etc operating properly. No XCode warnings and builds all working. I can attach relevant code if that would help. What am I missing?

Simulator screen shots

2      

I haven't tried it myself, but theoretically constraining WKWebView to safe areas should work. As far as I remember view is not constrained there in storyboard so it takes all space available.

UPD: Confirmed by using this code.

  • First, comment out override func loadView()
  • Second, in your viewDidLoad add these lines at the beginning

      webView = WKWebView()
      webView.navigationDelegate = self
      webView.translatesAutoresizingMaskIntoConstraints = false
      view.addSubview(webView)
    
      let safeGuide = view.safeAreaLayoutGuide
      webView.leadingAnchor.constraint(equalTo:safeGuide.leadingAnchor, constant: 0).isActive = true
      webView.trailingAnchor.constraint(equalTo:safeGuide.trailingAnchor, constant: 0).isActive = true
      webView.topAnchor.constraint(equalTo:safeGuide.topAnchor, constant: 0).isActive = true
      webView.bottomAnchor.constraint(equalTo:safeGuide.bottomAnchor, constant: 0).isActive = true

2      

So if I read this right, you turn off the Automask constraints then specifically set the safe area constraint anchor points on.

This worked. Thanks.

2      

To fix the issue we need to understand what is happening on the screen. I don't know the level of your knowledge of UIKit so I will try to encompass as much as possible.

So let's start with Paul's example.

  • UIKit works with view controllers. The purpose of view controller is to manage the scene's main view and its content. For this purpose, the UIViewController class defines the following property. view - This property sets or returns the UIView object that represents the scene's main view. When the app is launched, a UIView object is created to represent the scene's main view and this object is assigned to the view property. From this property, we can modify the attributes of the view.
  • loadView() is a UIViewController method and is responsible for making the view property exist in the first place. When using Storyboards, this is the method that will load your nib file and attach it to the view, but when instantiating view controllers manually, all this method does is create an empty UIView. You can override it to change this behavior and add any kind of view to the view controller's view property.
  • By default, since iOS15, UIKit bars have transparent backgrounds unless a scroll view is scrolled underneath the bar.

So taking into consideration all the above we can conclude the following. Paul, by using loadView() assigns WKWebView to view property of UIViewController class. WKWebView occupies the whole screen, so when we add NavigationController's navigation bar to hierarchy it is placed on top of view and as navigation bar is transparent we can see WKWebView

How we can fix that (One of many solutions)

  • We will not override loadView() method and will use viewDidLoad()instead to add WKWebView and later constrain the layout of WKWebView.
  • In viewDidLoad() we add WKWebView as a subview
  • When elements are introduced to the interface without constraints, XCode uses system called Autoresizing to position and size them. The information generated by this system is later applied to create constraints for the elements and presents the interface on the screen. If the constraints are added from the code (as in our case), the system doesn't know that there are constraints available and tries to create its own. To tell the system that Autoresizing constraints are not necessary, we must set the view's translatesAutoresizingMaskIntoConstraints property to false. Assigning the value false to this property avoids the creation of automatic constraints and ensures that those you define in code will not conflict with those defined by the system. The property must be defined for every view added to the interface.
  • And finally we add constraints to WKWebView so that it stays in safe area bounds. And now there is no overlapping with navigaiton bar.

Hope this make sense now.

3      

I appreciate the depth/detail of the response. It's very helpful for understanding the "why". Thanks again.

2      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.