Swift Wkwebview Replace Upload Button With Camera Feed
An Extensive Guide to WKWebView
Past | Last Updated on Dec eighth, 2021 12:00 pm |five-min read
You use WKWebView to display interactive spider web content in your app. Ideal for displaying HTML markup, styled text content, or complete web pages. It's similar having a small web browser right in your app!
In this tutorial you'll learn:
- How to utilise WKWebView with Swift
- How to respond to events and user interaction with delegation
- Why WKWebView is useful, and in what scenarios
- Some quick tips, like getting the spider web page content size
The WKWebView component is a replacement for the legacy UIWebView component. Since iOS 12, UIWebView has been deprecated from the iOS SDKs and replaced with WKWebView. If your app uses UIWebView, you'll need to upgrade it to apply WKWebView. Don't worry, UIWebView and WKWebView are like in nature!
The WKWebView class can be used to display interactive web content in your iOS app, much like an in-app browser. Information technology'southward part of the WebKit framework and WKWebView uses the same browser engine as Safari on iOS and Mac.
Calculation a web view to your app is equally uncomplicated every bit adding a UIView or UIButton to your view controller in Interface Builder. Hither'south how:
- Open the XIB or Storyboard you want to add the web view to in Interface Builder
- Find the web view or WKWebView in the Object Library at the lesser-left of Interface Builder
- Drag-and-drop a WKWebView object from the Object Library to your view controller'due south canvas, and adjust its size and position
It'due south recommended to create an outlet for the web view in your view controller grade, such every bit:
@IBOutlet weak var webView:WKWebView?
Don't forget to connect the outlet in Interface Architect! And yous'll need to import the WebKit framework besides, at the top of your view controller:
import WebKit
Crawly! Let's load some interactive web content in that WKWebView object.
First, we'll create an instance of URLRequest with the data about the URL we want to load. Similar this:
allow request = URLRequest(url: URL(string: "https://learnappmaking.com")!)
Here's what happens:
- We're creating an case of URL by providing it a URL string https://learnappmaking.com. The initializer URL(string:) is failable, so it will return nil if the provided cord is an invalid URL.
- We're 100% certain we've provided a valid URL, so we're using force unwrapping to unwrap the optional.
- The URL object is so provided to the URLRequest initializer, which then assigns a URLRequest object to the asking constant.
Side by side, we'll use this asking to load the URL in the webview. Like this:
webView?.load(request)
Bold you lot're using a WKWebView in your view controller, you would add the above code to the viewDidLoad() function. Like this:
override func viewDidLoad()
{
super.viewDidLoad()
permit request = URLRequest(url: URL(cord: "https://learnappmaking.com")!)
webView?.load(asking)
}
When you run your app, you'll see that the spider web folio shows up! And it'due south completely interactive, then you can navigate the web page like an ordinary browser.
The nigh simple form of a web view is really blank-basic! You tin can, however, interact with the web view using a number of backdrop, objects and consul protocols.
A WKWebView web view has two main delegate protocols and properties:
- navigationDelegate of blazon WKNavigationDelegate, which responds to navigation events
- uiDelegate of blazon WKUIDelegate, which responds to user interaction events
Of these two consul protocols, the WKNavigationDelegate is probably used most ofttimes. And then, permit'due south hook into some page navigation events! We'll do so with these delegate functions:
- webView(_:didStartProvisionalNavigation:)
- webView(_:didCommit:)
- webView(_:didFinish:)
- webView(_:didFail:withError:)
- webView(_:didFailProvisionalNavigation:withError:)
Showtime, let's adopt the protocol and set the webView delegate. Here's how:
- Add the WKNavigationDelegate protocol to your view controller'due south course proclamation, similar: form WebViewController: UIViewController, WKNavigationDelegate
- Set the navigationDelegate belongings of webView to cocky, before loading the web request, like: webView?.navigationDelegate = self
Next, implement the five delegate functions described earlier. Set their function bodies to print(#function), so we tin can see the social club in which the functions are chosen.
Like this:
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
{
print(#office)
}
Echo this for the other iv delegate functions.
Finally, run the app! In the Console you lot see the order in which the delegate functions are called:
- webView(_:didStartProvisionalNavigation:)
- webView(_:didCommit:)
- webView(_:didFinish:)
The outset office webView(_:didStartProvisionalNavigation:) is chosen when the web view starts navigating to a page. At this indicate the URL request has just been sent to the webserver and no response has come back yet.
The 2d webView(_:didCommit:) function is chosen when the web view starts receiving data from the spider web server. At this point information technology will attempt to load the web folio HTML, every bit data is coming in.
The 3rd role webView(_:didFinish:) is called when the navigation is finished and all information has come in. This result usually coincides with the DOMContentLoaded JavaScript consequence, but keep in heed that webView(_:didFinish:) tin can besides be called before the HTML DOM is ready.
So, when are the mistake functions chosen? Permit's find out!
- First, change the spider web page URL of the web view to http://example.com
- And so, add together print(mistake) to the two error functions. so nosotros can see the error message
- Finally, run the app over again
You should now see an error message in the Panel:
The resources could not be loaded because the App Ship Security policy requires the use of a secure connexion.
This happens because you're simply allowed to load HTTPS URLs on iOS by default. You lot can't load an HTTP URL, like nosotros did, without irresolute the and so-chosen App Transport Security settings.
Then, what practise y'all use all these delegate functions for?
- You tin can show a network action spinner when a page navigation starts
- And stop the network activity indicator when navigation stops
- You lot can show an warning controller dialog when errors occur
And that's not everything, you can for example utilize the webView(_:decidePolicyFor:decisionHandler:) function to decide if a page navigation is immune. And you can respond to redirects, HTTP Hallmark challenges, and use crash recovery.
A web page and an app are two singled-out environments. Technically, a web folio doesn't "know" it's running inside a WKWebView. And vice-versa, yous can create total-fledged web apps that run inside Safari on iOS.
How do you lot interact with a web page in a WKWebView? You've got several options.
Uncomplicated navigation and interactions happen straight with functions on the webview instance, such as:
- load(_:mimeType:characterEncodingName:baseURL:) and loadHTMLString(_:baseURL:) to load web pages, and HTML directly
- estimatedProgress, isLoading and hasOnlySecureContent to get the state of the web folio
- reload() and stopLoading() to respectively reload and stop loading the page
- goBack(), goForward() and go(to:) for history-based navigation, like a normal web browser
- canGoBack, canGoForward and backForwardList to get information about navigation history
Then of course, at that place's JavaScript. JavaScript is used to lawmaking things in web browsers. JavaScript is enabled in a WKWebView by default, and you lot tin can apply it to practise a one thousand-and-1 things. Unfortunately, JavaScript-based interaction betwixt the web view and your app is… interesting, to say the least.
Evaluating JavaScript
Yous have one function at your disposal: evaluateJavaScript(_:completionHandler:). When yous call this function on a WKWebView example, a string of JavaScript is sent to the web page and evaluated. When evaluation is washed, its event is returned with the completionHandler closure.
We're going to execute some JavaScript. Change the webView(_:didFinish:) part into the following:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
{
webView.evaluateJavaScript("navigator.userAgent", completionHandler: { outcome, error in
if let userAgent = result as? String {
print(userAgent)
}
})
}
Here'due south what happens when the spider web view finishes navigation:
- We send a JavaScript string to the web view. The navigator.userAgent is a browser property that contains the User Agent Cord, which is a bit of text that identifies the type/model of the browser that'south loading the spider web page.
- When the JavaScript has been evaluated, the result is provided to a completion handler. We've provided a simple closure that prints out the userAgent abiding if it's a value of type Cord.
Yous tin can evaluate almost whatsoever kind of JavaScript lawmaking. That means you can inspect elements, check the values of properties, and assign event handlers.
The downside of this approach is that information technology'due south only i way: you can inject JavaScript in the web page, simply you tin't respond to events happening in the web view from within the web view itself.
JavaScript with WKUserScript
Yous can utilize an alternative approach to piece of work with JavaScript and WKWebView, and that'southward past using a WKUserScript. Here'due south how:
let config = WKWebViewConfiguration()
let js = "certificate.addEventListener('click', function(){ window.webkit.messageHandlers.clickListener.postMessage('My hovercraft is full of eels!'); })"
allow script = WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: imitation)
config.userContentController.addUserScript(script)
config.userContentController.add(self, name: "clickListener")
webView = WKWebView(frame: view.bounds, configuration: config)
view.addSubview(webView!)
Next, make sure to adopt the WKScriptMessageHandler delegate protocol in your view controller's form declaration. And add the following function to your view controller:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
{
print(bulletin.body)
}
What happens here?
The scarlet thread here is that we're creating an instance of WKWebView manually, and assign it a WKWebViewConfiguration object. This configuration object gets a WKUserScript object, which contains JavaScript code.
The JavaScript code attaches an upshot listener to the web page. This will mail a message to the clickListener bulletin handler whatever time a click event happens on the spider web page.
The user script also attaches to that same clickListener handler. And so, when the bulletin "My hovercraft is full of eels!" gets posted to the message handler, the delegate function userContentController(_:didReceive:) gets called on your view controller. This effectively sends a message from the web folio to your iOS app, and that'southward something nosotros couldn't do before!
If you use the above code sample with the code yous've written previously in this tutorial, make sure to disable the outlet and remove the WKWebView instance from your view controller in Interface Architect first.
The usefulness of WKWebView goes beyond displaying uncomplicated web pages in your app. After all, nearly of what you can practise on a web page you tin code natively in your iOS app – and so why apply web views at all?
One particularly useful scenario is when you want to create a layout or user interface with HTML. Imagine you're making a recipe app and you desire to prove detailed data about the recipe, in a detail view controller.
Yous could create the entire user interface natively, with views, buttons and labels. Y'all could as well create that same user interface with HTML and CSS. You could even store the recipe HTML pages on a webserver, and update them on-the-fly.
The WKWebView function you lot need at this betoken is loadHTMLString(_:baseURL:). With this function you can load HTML straight in the web view.
Like this:
webView.loadHTMLString("So long and thanks for all the fish!", baseURL: nil)
This will bear witness a bold string of text in the spider web view. And of course, you can load any kind of HTML and CSS in the web view.
The baseURL parameter allows you lot to ready a base of operations URL for the web page, like the HTML
Keep in mind that any HTML page needs and tags, although a spider web view will likewise part OK without them.
Here's a useful snippet that sets an initial viewport with, and uses iOS'south default San Francisco font:
\(html)
When y'all assign the above snippet to your web view, make sure that the variable html contains your folio's HTML string.
And here'south something else… Imagine you're building your recipe app and y'all want to brandish a web view below some native views, such every bit an image view and a few labels. You add these views, including the web view, in a scroll view, and then the user tin coil the unabridged stack of views from superlative to lesser.
You at present accept a trouble, because both the scroll view and the web view can coil!
The solution here is equally follows:
- Pivot the spider web view to the leading, trailing, top and bottom edges with Auto Layout constraints
- Give the spider web view a dynamic height constraint, i.due east. connect the constraint to the outlet and so you tin can ready it'south abiding property
- Get the inner content size of the web page, and dynamically set the height of the web view to match the peak of the spider web page (with the constraint)
- Optionally, disable scrolling on the spider web view
As a result, the web view resizes itself to friction match its inner content peak. This will fit vertically in the ringlet view, which you tin at present scroll from height to bottom without scrolling the web view itself.
First, make certain y'all've set up the constraints of your web view and added an outlet of blazon NSLayoutConstraint for the heightConstraint of the spider web view itself.
Then, add the following lawmaking to your view controller:
webView.evaluateJavaScript("document.readyState", completionHandler: { effect, fault in
if result == nil || error != nil {
return
}
webView.evaluateJavaScript("document.trunk.offsetHeight", completionHandler: { result, error in
if permit superlative = result as? CGFloat {
self.heightConstraint?.constant = peak
}
})
})
Sample lawmaking adapted from IvanMih's.
The in a higher place code evaluates two bits of JavaScript. Information technology'll first read the readyState of the web page, and then it'll read the offsetHeight of the document body. This matches the height of the web folio, which we subsequently utilise to set the heightConstraint on the spider web view.
The above code works fine with iOS 12 and Swift five. Unfortunately, web pages typically have a lot of moving pieces, and then your mileage may vary. What'south important is to evaluate the height of the web folio as late as possible, but not afterward. Y'all desire to become the content elevation as before long as the page has finished loading completely.
And that concludes our exploration of WKWebView. The web view is quite a powerful component, albeit tricky to work with too.
We've looked at loading a simple web page in WKWebView and responding to navigation events. You've inserted JavaScript into the page, with two methods, and used uncomplicated commands to navigate and inspect the spider web view. And we've looked at different scenarios in which a web view might come in handy.
Create Your App At present
✖
Subscribe to our newsletter
crandelladder1983.blogspot.com
Source: https://www.appypie.com/wkwebview-how-to
0 Response to "Swift Wkwebview Replace Upload Button With Camera Feed"
Post a Comment