WKWebView in iOS app takes a long time to load
Apparently the delay is caused by the time it takes to make a new instance of WKWebView
, not the time it takes to load an HTML document. To avoid that delay I figured out a way to reuse a web view.
First I removed the web view from the storyboard scene so that a new web vew wouldn't be created every time the view was loaded. I made a generic view named container
that is the same size that I wanted the web view to be.
Then I made a static variable to keep a pointer to the web view:
static var webView: WKWebView? = nil
In my case this static variable is in a class called GameController
.
Next I changed the code to check to see if the static webView
variable is nil. If webView
is nil, the code creates a new web view and sets the static variable to point to that web view. Then the code programmatically adds the web view as a subview of a container view in the storyboard scene.
To set up the storyboard and write this code I used the explanation on the following web site:
http://www.onebigfunction.com/ios/2016/12/14/iOS-javascript-communication/
The basic code in the view controller for the scene that uses the web view (WebViewController
in my code) looks like this:
override func loadView() {
super.loadView()
if GameController.webView == nil {
var webFrame = self.container!.frame
webFrame.origin.x = 0
webFrame.origin.y = 0
let config = WKWebViewConfiguration()
webView = WKWebView(frame: webFrame,
configuration: config)
GameController.webView = webView
} else {
webView = GameController.webView
}
self.container!.addSubview(webView)
}
In my case, I wanted to send information from JavaScript code in the web view to Swift code in my app, so I had to work more with configurations. I also wanted the web view to be transparent, so I added a statement to do that.
override func loadView() {
super.loadView()
if GameController.webView == nil {
var webFrame = self.container!.frame
webFrame.origin.x = 0
webFrame.origin.y = 0
let config = WKWebViewConfiguration()
config.userContentController.add(self, name: "scriptHandler")
webView = WKWebView(frame: webFrame,
configuration: config)
webView.isOpaque = false
GameController.webView = webView
} else {
webView = GameController.webView
webView.configuration.userContentController.removeScriptMessageHandler(
forName: "scriptHandler")
webView.configuration.userContentController.add(self,
name: "scriptHandler")
}
self.container!.addSubview(webView)
}
Originally I only set the script handler when I first made the web view, but that didn't work. Apparently a new view controller object was made each time the scene was loaded, so the old script handler didn't work. This code deletes the script handler that pointed to the old view controller and adds a script handler that points to the new view controller.
WKWebView catch HTTP error codes with Swift 4
Using a WKNavigationDelegate
on the WKWebView
you can get the status code from the response each time one is received.
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if let response = navigationResponse.response as? HTTPURLResponse {
if response.statusCode == 401 {
// ...
}
}
decisionHandler(.allow)
}
WKWebView Navigation Delegate Not Called
You need to move let test = TestWebview ()
to class level, otherwise this object is going to be evicted when viewDidLoad
completes: the navigationDelegate
is defined as weak
, so it's not going to prevent it either.
Related Topics
How to Call Objective-C Instancetype Method in Swift
Can Push Notifications Be Used to Run Code Without Notifying User
Disabling Allowsbackgroundlocationupdates (Cllocationmanager) Doesn't Work After Is Was Enabled
Sync Video in Avplayerlayer and Avplayerviewcontroller
Cloudkit Push Notifications on Record Update Stopped Working
How to Configure Threshold/Distance When Swiping on Uitableviewcell
Dateformatter Gives Wrong Time on Conversation
Strange Custom Background Color on Uipickerview Swift
Swift: Iboutlets Are Nil in Custom Cell
Swiftui Xcode 12.3 Can't Change Button Size in Toolbar
How to Keep Spritekit Scene Paused When App Becomes Active
Left-To-Right Mark Not Working in Swift
Whats the Correct Way, Using "Init" or "Didmove"
Fix Cursor Size for Modified Paragraph Spacing in Uitextview
In What Format Is This Date String
How to Make a Reusable Tableview for Different Screens in the Same Application
Stick UItableview Header View to Top When Creating Header in Storyboard