WebKit Frame at A Glance (A look at the WebKit Framework) – Part 1

Source: Internet
Author: User


A look at the WebKit Framework–part 1


If you've ever built an application that required a webview to the load Web content in your native app and then you have probably Experienced the frustrations that came with using UIWebView. UIWebView is quite limited, and its performance lags behind, that's Mobile Safari. JavaScript, which powers just about every Web application, performs poorly in native mobile applications.

However, all of this have changed with the introduction of the WebKit framework in IOS 8. With the WebKit framework, comes Wkwebview which replaces UIWebView in UIKit and WebView in AppKit, offering a consistent API across the platforms.

The WEBKIT framework enables developers to create web enabled native apps that can utilize the power and speed of Nitro, W Hich is the JavaScript engine, that powers Safari.

Wkwebview boasts of 60fps smooth scrolling, KVO, built-in gestures and native communication between app and webpage.

In the span of the articles, we'll build the applications which would explore some of the features that WebKit (in Particul AR, Wkwebview) offers. For the first application (built in this tutorial), we'll create a Web browser that have some of the functionalities of SAF Ari. The second article would go deeper into Webkit and show the more powerful features like injecting JavaScript into a web Pag E to modify content and extract data.

Getting Started

To get started, create a new project. Make it a single View application named Browser and select Swift as the language and make it Universal.

In Viewcontroller.swift import the WebKit framework.

1
Import WebKit

Next Add the following variable to the class.

1
var Webview:wkwebview

Add The following method to the class. It initializes the Web view with frame of size zero. Later we'll add auto layout constraints to the webview so it adapts to whichever device and orientation it's run on.

1
2
3
4
Required Init (coder Adecoder:nscoder) {
Self.webview = Wkwebview (Frame:cgrectzero)
Super.init (Coder:adecoder)
}

At the bottom of viewdidload () Add the following statement which would add the WebView to the main View.

1
View.addsubview (WebView)

Next Add the following constraints at the bottom of viewdidload ()

1
2
3
4
Webview.settranslatesautoresizingmaskintoconstraints (False)
Let height = nslayoutconstraint (Item:webview, attribute:. Height, Relatedby:. Equal, Toitem:view, attribute:. Height, Multiplier:1, constant:0)
Let width = nslayoutconstraint (Item:webview, attribute:. Width, Relatedby:. Equal, Toitem:view, attribute:. Width, Multiplier:1, constant:0)
View.addconstraints ([height, width])

Here we first disable auto-generated constraints with the first statement and then we define the height and width constrai NTS for the WebView. The WebView'll has the same height and width as its Superview's height and width.

WE ll load a default URL when the app starts. Later we ' ll add a text field that the user can use to enter a URL. Add the following at the bottom of viewdidload ()

1
2
3
Let URL = Nsurl (string: "http://www.appcoda.com")
Let request = Nsurlrequest (url:url!)
Webview.loadrequest (Request)

Run the application. It'll load the homepage of Appcoda. When you are scroll down, notice so can see the page scrolling underneath the translucent navigation bar. We ' ll disable this. Open Main.storyboard and select the View Controller. In the Attributes Inspector, uncheck the under Top Bars option in the Extend Edges group. When you run the app again, the Nav bar should now is solid and you won ' t see the webpage underneath it.

Next we ll enable URL input from the user.

In the storyboard file, drag a view onto the navigation bar in the View controller. In the Attribute Inspector, set it Background to Clear Color. Since you can ' t apply auto layout constraints within a navigation bar, we'll set its size in code.

Open the Assistant Editor and create an outlet for the view by control-dragging from the view to the Viewcontroller class. Name the outlet Barview. You should has the following in your code.

1
@IBOutlet weak var barview:uiview!

Add the following to Viewdidload () after the call to Super.viewdidload ()

1
Barview.frame = CGRect (x:0, y:0, Width:view.frame.width, height:30)

This sets the size of the Barview when the app loads.

Add The following method to the class.

1
2
3
Override Func Viewwilltransitiontosize (Size:cgsize, Withtransitioncoordinator Coordinator: Uiviewcontrollertransitioncoordinator) {
Barview.frame = CGRect (x:0, y:0, Width:size.width, height:30)
}

This would set the size of the Barview when the device orientation changes.

On running the app you should see the view stretched off on the navigation bar. When you change orientations or devices, the view adapt its size accordingly.

Next Drag a Text Field onto the view. The Using the pin button at the bottom of the canvas, Pin it top, bottom, right and left with a spacing of 0.

Fix the Auto layout issues by selecting Editor > Resolve Auto layout issues > Selected View > Update
Frames

Create an outlet for the text field. Name it Urlfield. You should has the following.

1
@IBOutlet weak var urlfield:uitextfield!

We want the view controller to receive Uitextfielddelegate protocol methods, so in the Document Outline, Control-drag from The text field to the View controller and select Delegate from the popup.

With the text field selected, set the following in the Attributes Inspector.

    • Clear Button:appears while editing
    • Correction:no
    • Keyboard Type:url
    • Return Key:go

The change of the class declaration as follows so, it conforms to the Uitextfielddelegate protocol.

1
Class Viewcontroller:uiviewcontroller, Uitextfielddelegate

Next Add the following Uitextfielddelegate protocol method to the class.

1
2
3
4
5
Func Textfieldshouldreturn (Textfield:uitextfield)-> Bool {
Urlfield.resignfirstresponder ()
Webview.loadrequest (Nsurlrequest (Url:nsurl (string:urlField.text)!))
return False
}

This dismisses the keyboard and loads the URL of given by the user. Test it with a URL. You have the-to-enter the full URL, i.e. http://google.com. Since This can is a bit cumbersome to your users, you could write code that checks the URL of string for '/HTTP ' and if not Present, appends it to the beginning of the URL string, thus allowing users to enter such URLs as Google.com. We won ' t get into this here.

Navigating Through History

Our browser are working but still lacks some features the we ' ve come to expect of web browsers, namely loading indicator, Back and Forward buttons, reload button e.t.c.

With KVO (Key Value Observing) loading progress, page title and URL is now observable properties of Wkwebview. You can use the these values to update your UI accordingly.

First, we ll add the back, forward and reload buttons.

In the storyboard, select View Controller and then on the Attributes Inspector, under simulated Metrics, change Bottom Bar To None.

Drag a Toolbar onto the view and place it at the bottom. Pin its-left, right and bottom with a spacing of 0, making sure constrain to margins are unchecked.

In Viewdidload () Edit the WebView ' s height constraint-to-take the-into account.

1
Let height = nslayoutconstraint (Item:webview, attribute:. Height, Relatedby:. Equal, Toitem:view, attribute:. Height, Multiplier:1, constant:-44)

Remove the existing button item from the toolbar and drag the following on Order:a Bar button item, a Fixed Space Bar but ton item, a bar button item, flexible Space Bar button item and a bar button item. The toolbar should look as shown.

Edit the bar button items text to and R respectively. These'll is our back, Forward and Reload buttons. In a real app, it would is better to use icons on the buttons, but for ease, we'll use text. The toolbar should look as shown.

Create outlets for each of the bar button items. Name them Backbutton, Forwardbutton and Reloadbutton respectively. You should has the following in your code.

1
2
3
@IBOutlet weak var backbutton:uibarbuttonitem!
@IBOutlet weak var forwardbutton:uibarbuttonitem!
@IBOutlet weak var reloadbutton:uibarbuttonitem!

Then create actions for the same buttons and name them back, forward and reload respectively. For each action, the change of the Type to Uibarbuttonitem. You should has the following in your code.

1
2
3
4
5
6
7
8
@IBAction func Back (Sender:uibarbuttonitem) {
}

@IBAction func Forward (Sender:uibarbuttonitem) {
}

@IBAction func Reload (sender:uibarbuttonitem) {
}

At the bottom of viewdidload () add the following. We don ' t want the back and forward buttons to is enabled when the app first loads.

1
2
Backbutton.enabled = False
Forwardbutton.enabled = False

Add the following to Viewdidload () After the constraints is added, and before the code that creates and loads a request. This adds the class as a observer of the loading property.

1
Webview.addobserver (Self, Forkeypath: "Loading", Options:. New, Context:nil)

Add The following method to the class. It'll be called whenever the observable property changes. The state of the back and forward buttons would be changed according to the current state of the Web view.

1
2
3
4
5
6
Override Func Observevalueforkeypath (keypath:string, Ofobject object:anyobject, change: [Nsobject:anyobject], context : Unsafemutablepointer) {
if (KeyPath = = "Loading") {
backbutton.enabled = Webview.cangoback
forwardbutton.enabled = Webview.cangoforward
}
}

Modify the Back (), forward () and reload () functions as shown.

1
2
3
4
5
6
7
8
9
10
11
12
@IBAction func Back (Sender:uibarbuttonitem) {
Webview.goback ()
}

@IBAction func Forward (Sender:uibarbuttonitem) {
Webview.goforward ()
}

@IBAction func Reload (sender:uibarbuttonitem) {
Let request = Nsurlrequest (url:webview.url!)
Webview.loadrequest (Request)
}

Run the application and test the buttons. The back and forward should is disabled at first. When you navigate to a page, the Back button should is enabled. When you go back, the Forward button should is enabled. Tapping R should reload the page.

Handling Errors

You can ' t always rely the correct URL of the user to always type. We ll write code to catch errors and notify the user.

First modify the class declaration as shown.

1
Class Viewcontroller:uiviewcontroller, Uitextfielddelegate, wknavigationdelegate

The Wkwebview have a property named Navigationdelegate which expects an object that conforms to the Wknavigationdelegate PR Otocol. The Protocol provides different methods dealing with navigation events, including loading errors.

Add the following to the bottom of init (). With this, the class would be the navigation delegate of the Web view.

1
Self.webView.navigationDelegate = Self

Next Add the following method to the class. This is the delegate method, which gets called when there was an error.

1
2
3
4
5
Func WebView (webview:wkwebview!, didfailprovisionalnavigation navigation:wknavigation!, Witherror error:nserror!) {
Let alert = Uialertcontroller (title: "Error", Message:error.localizedDescription, Preferredstyle:. Alert)
Alert.addaction (uialertaction (title: "OK", Style:.) Default, Handler:nil))
Presentviewcontroller (Alert, animated:true, Completion:nil)
}

Run and test the app with an incorrect URL.

Displaying Progress

To finish off, we'll add a progress indicator to the app.

In the storyboard file, drag a Progress view onto the view and place it below the navigation bar. Pin its top, right and left as shown.

Create an outlet for the Progress View and name it Progressview. You should has the following.

1
@IBOutlet weak var progressview:uiprogressview!

In Viewcontroller, replace the statement

1
View.addsubview (WebView)

With this

1
View.insertsubview (WebView, Belowsubview:progressview)

In Viewdidload (), add the following below the statement this calls Addobserver () on the WebView, before the creation and L Oading of the URL request.

1
Webview.addobserver (Self, Forkeypath: "Estimatedprogress", Options:. New, Context:nil)

Add the following to the bottom of Observevalueforkeypath () after the other if statement.

1
2
3
4
if (KeyPath = = "Estimatedprogress") {
Progressview.hidden = Webview.estimatedprogress = = 1
Progressview.setprogress (Float (webview.estimatedprogress), animated:true)
}

This updates the progress view as the value of estimatedprogress changes or hides it when loading completes.

Add The following method to the class. It's a wknavigationdelegate protocol method that gets called when the page load completes. We use it here to reset the progress view value through each request.

1
2
3
Func WebView (webview:wkwebview!, didfinishnavigation navigation:wknavigation!) {
Progressview.setprogress (0.0, Animated:false)
}

Run the app and you should see a blue progress line as the app loads.

Conclusion

We have looked at the basics of the new WebKit framework. We ' ve seen how to add some of the features offered by Safari, namely loading URLs, navigating through history, detecting a nd handling errors and displaying progress. In part 2 of the This tutorial, we'll go deeper into webview and look at what to inject JavaScript into a Web page to build a M Ore powerful application.

You can download the code to this tutorial here.




WebKit Frame at A Glance (A look at the WebKit Framework) – Part 1

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.