speg
speg

Reputation: 2019

How to create a sized WKWebView in Swift 3 / iOS 10

I am attempting to add a WKWebView to my app that takes up about ~2/3 of the screen (leaving space at the bottom). Because there seems to be no way to add the WKWebView to the storyboard, I added a regular UIView. Then in my viewDidAppear method I try and create a WKWebView with the same bounds. Is this a sound approach?

My code looks like this:

    @IBOutlet var conversationView: UIView!

    override func viewDidAppear(_ animated: Bool) {
      let webView = WKWebView(frame: conversationView.frame)
      if let url = URL(string: "https://www.google.com") {
        webView.load(URLRequest(url: url))
      }

      // conversationView = webView // <-- doesn't work :\
      conversationView.addSubview(webView) // works!
    }

Swaping the views outright doesn't work at all, so instead I add the web view as a subview of the temporary view I added to the storyboard. This at least lets me constrain it's position and size but still it feels very kludgy and like there must be a better way of doing this..

Screenshot

Upvotes: 6

Views: 6541

Answers (5)

Rohit Makwana
Rohit Makwana

Reputation: 4905

You can try this hope it works

Note: Please set Frame according to your requirements.

import UIKit
import WebKit

class WKWebViewVC: UIViewController {

    @IBOutlet weak var wkWebviewBGView: UIView!
    var wkWebview: WKWebView!

    override func viewDidLoad() {

       super.viewDidLoad()

       wkWebview = WKWebView(frame: wkWebviewBGView.bounds, configuration: WKWebViewConfiguration())
       wkWebview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
       self.wkWebviewBGView.addSubview(wkWebview)

       let url = URL(string: "https://www.google.com")
       wkWebview.load(URLRequest(url: url!))
   }
}

Upvotes: 0

Dale
Dale

Reputation: 3323

None of the other answers worked for me. The answer by Samip Shah is along the right track but the constraints are not quite correct. The important thing to remember is to set translatesAutoresizingMaskIntoConstraints to false.

So, here's my solution. In the storyboard create a UIView with the constraints and layout you want for the WKWebView. In your view controller add the code:

@IBOutlet var contentView: UIView!
var wkWebView:WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()

    wkWebView = WKWebView(frame:contentView.frame)
    contentView.addSubview(wkWebView)
    constrainView(view: wkWebView, toView: contentView)

    let request = URLRequest(url: /* your url here */)
    wkWebView.load(request)
}

The code for constraining the view. You might add this to a utilities class if you want to use it more than one view controller.

func constrainView(view:UIView, toView contentView:UIView) {
    view.translatesAutoresizingMaskIntoConstraints = false
    view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
    view.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}

Upvotes: 8

Samip Shah
Samip Shah

Reputation: 874

If you want to give constraints that size and postion the webview with respect to its container view, you can do like this.

     @IBOutlet weak var wkWebBackgroundView: UIView!
     var wkWebView:WKWebView!

     override func viewDidLoad() {
            super.viewDidLoad()
            setUpView()

        }
     func setUpView(){
            self.wkWebView = WKWebView(frame: CGRect.zero)     
            self.wkWebBackgroundView.addSubview(wkWebView)

            let height = NSLayoutConstraint(item: wkWebView, attribute: .height, relatedBy: .equal, toItem: wkWebBackgroundView, attribute: .height, multiplier: 1, constant: 0)
            let width = NSLayoutConstraint(item: wkWebView, attribute: .width, relatedBy: .equal, toItem: wkWebBackgroundView, attribute: .width, multiplier: 1, constant: 0)
            let top = NSLayoutConstraint(item: wkWebView, attribute: .top, relatedBy: .equal, toItem: wkWebBackgroundView, attribute: .top, multiplier: 1, constant: 0)
            let leading = NSLayoutConstraint(item: wkWebView, attribute: .leading, relatedBy: .equal, toItem: wkWebBackgroundView, attribute: .leading, multiplier: 1, constant: 0)

            view.addConstraints([leading, top, height, width])  
        }

Upvotes: 1

JustinM
JustinM

Reputation: 2222

You can just size the webview frame as desired without using a different view.

let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height * 0.66).integral)
view.addSubview(webView)

However, if you need the view in the storyboard to line up other subview constraints then your method works fine.

Edit: Just saw your added screenshot with comment stating the view is below a label:

let webView = WKWebView(frame: CGRect(x: label.frame.maxX + (whatever distance you want between label bottom and webView top), y: 0, 
width: view.bounds.width, height: view.bounds.height * 0.66).integral)
view.addSubview(webView)

Upvotes: 0

matt
matt

Reputation: 535860

That's a very good approach; it is perfectly reasonable to have a "content view" whose job is merely to guide the web view into place, as it were. But it would be even better to add the web view plus constraints that size and position it.

Upvotes: 1

Related Questions