你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS 8 WebKit框架概覽(上)

iOS 8 WebKit框架概覽(上)

編輯:IOS開發基礎

(原文:A Look at the WebKit Framework – Part 1 作者:Joyce Echessa 譯者:ibenjamin )

如果你曾經在你的App中使用UIWebView加載網頁內容的話,你應該體會到了它的諸多不盡人意之處。UIWebView是基於移動版的Safari的,所以它的性能表現十分有限。特別是在對幾乎每個Web應用都會使用的JavaScript,表現的尤為糟糕。

但是,所有的這一切都在iOS 8引入了一個新的框架——WebKit,之後變得好起來了。在WebKit框架中,有WKWebView可以替換UIKit的UIWebView和AppKit的WebView,而且提供了在兩個平台可以一致使用的接口。

WebKit框架使得開發者可以在原生App中使用Nitro來提高網頁的性能和表現,Nitro就是Safari的JavaScript引擎。

WKWebView保證在滑動時保持60的幀率,同時具有KVO,內建手勢,以及在App和網頁之間的原生交流方式。

橫跨2篇文章,我們即將建立2個App來探索WebKit的功能(特別是WKWebView)。在第一個App當中,我們將建立一個和Safari 功能相似的浏覽器。在第二篇文章中,我們會深入到Webkit中去,探索更強大的功能:注入JavaScript到網頁以改變內容和獲取數據。

開始

打開Xcode,創建一個新的工程。選擇Single View Application,取名叫Browser,選擇Swift為開發語言,Devices選擇Universal。

在ViewController.swift中導入WebKit框架。

import WebKit

將下面的變量加入到類中

var webView: WKWebView

將下面的方法加入到類中。它將會初始化webview並設置其frame為0.稍後我們會使用自動布局(auto layout)來給webview添加約束,這樣這個webview就能在任何蘋果設備和任何方向上正常工作了。

required init(coder aDecoder: NSCoder) {
    self.webView = WKWebView(frame: CGRectZero)
    super.init(coder: aDecoder)
}

在viewDidLoad()底部,添加如下語句。這樣這個webView就被添加到主視圖了。

view.addSubView(webView)

接下來,在viewDidLoad()方法底部添加如下約束

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])

在此處,我們首先禁止了自動約束。然後我們對webview的寬和高添加了約束。這樣webview就會和它的superview擁有一樣的寬和高了。

在程序啟動時,我們將會打開一個默認頁。然後我們添加一個textfield控件,這樣用戶就能輸入自己想浏覽的地址了。在viewDidLoad()底部添加如下代碼

let url = NSURL(string:"http://www.appcoda.com")
let request = NSURLRequest(URL:url!)
webView.loadRequest(request)

運行程序。它將會加載Appcoda的主頁。注意當你滑動頁面的時候在導航欄下面也能看到模糊的網頁,我們將禁止這樣。首先打開 Main.storyboard選擇網頁顯示的ViewController。在屬性檢查(也就是右邊的第四欄中)將Extend Edges中得Under Top Bars去掉勾選。再次運行程序,我們就會發現導航欄已經沒有了毛玻璃效果,而且我們也不能看見它下面的網頁內容了。

接下來讓我們添加給用戶輸入URL的控件。

在storyboard文件中,給向導航欄中拖放一個view。在屬性檢查(右邊第四欄)中,設置其背景色為透明(clear color)。因為我們無法給導航欄中的view添加約束,我們將會以代碼的形式調整其大小。

@IBoutlet weak var barView: UIView!

在viewDidLoad()的super.viewDidLoad()之後添加如下代碼

barView.frame = CGRect(x:0, y: 0, width: view.frame.width, height: 30)

這段代碼設置了barView的大小。

將下面的方法添加到類

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    barView.frame = CGRect(x:0, y: 0, width: size.width, height: 30)
}

這段代碼將在設備方向改變時重新設置barView的大小。

接下來運行程序,你可以看見在導航欄中展開的view,如果更改設備方向,這個view也會跟著改變大小。

接下來,拖放一個textfield控件到這個view裡面。然後點擊畫布右下方的Pin按鈕(第二個)。將其top,bottom,right,left的距離設置為0,如下圖所示。

然後依次點擊,Editor-》Resolve Auto Layout Issues-》Selected View-》Update Frame,解決警告。

然後創建一個outlet。取名urlField。你應會看到如下代碼。

@IBOutlet weak var urlField: UITextField!

我們希望viewcontroller能成為UITextFieldDelegate的代理,在storyboard的Document Outline中,按下control然後將textfield拖放到viewcontroller,然後在彈出視圖選擇delegate。

選擇textfield控件,在屬性檢查(右邊第四欄)設置如下屬性。

  1. Clear Button:Appears while editing

  2. Correction: NO

  3. Keyboard Type:URL

  4. Return Key:Go

在類聲明部分添加實現UITextFieldDelegate代碼。

class ViewController: UIViewController, UITextFieldDelegate

接下來添加如下UITextFieldDelegate代碼

func textFieldShouldReturn(textField: UITextField) -> Bool {
urlField.resignFirstResponder()
webView.loadRequest(NSURLRequest(URL: NSURL(string: urlField.text)!))
return false
}

以上代碼會隱藏鍵盤,然後加載用戶輸入的url。嘗試輸入一個url,我們發現。我們必須輸入一個完整的url,比如:http://google.com。對我們的用戶這有一點麻煩,我們可以檢查用戶的輸入,然後給用戶輸入的url在必要時添加‘http://’前綴。這裡我們不會詳述了。

浏覽歷史

現在我們的浏覽器已經能工作了,但是它還缺少了一些浏覽器應有的功能。載入進度提示,前進和後退,刷新按鈕,等等。

通過KVO(Key Value Observing),我們可以監聽WKWebView的載入進度、網頁標題和url屬性。你可以使用這些來更新你的UI。

首先,讓我們添加後退、前進及刷新按鈕。

在storyboard中,選擇View Controller,點擊屬性檢查(Attributes Inspector),在Simulated Metrics一欄,將BottomBar選擇為None。

拖放一個Toolbar到view得底部。添加其left,right和bottom距離為0,並確保Constrans to margins一欄沒有被勾選。

在viewDidLoad()方法中調整webView的高度,以顯示toolbar。

let height = NSLayoutConstraint(item: webView, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 1, constant: -44)

移除toolbar中得button,然後按順序添加以下控件:Bar Button Item、Fixed Space Bar Button Item、Bar Button Item,Flexible Space Bar Button Item和Bar Button Item。toolbar應該是這個樣子。

編輯bar button成下面的樣子。這些按鈕將成為我們的前進後退及刷新按鈕。在一個真實的App當中,為這些按鈕放上圖標將是更好的選擇,但是為了簡便,我們使用文本。toolbar接下來應該是這個樣子。

為每一個bar button創建一個outlet。取名為backButton,forwardButton和reloadButton。你應該會得到如下代碼

@IBOutlet weak var backButton: UIBarButtonItem!
@IBOutlet weak var forwardButton: UIBarButtonItem!
@IBOutlet weak var reloadButton: UIBarButtonItem!

然後為每個按鈕依次分別創建back,forward和reload方法。將每個action的Type更改為UIBarButtonItem。你應該會得到如下代碼。

@IBAction func back(sender: UIBarButtonItem) {
}

@IBAction func forward(sender: UIBarButtonItem) {
}

@IBAction func reload(sender: UIBarButtonItem) {
}

在viewDidLoad()的底部添加如下代碼。我們不希望後退和前進按鈕在App被啟動時就可點擊。

backButton.enabled = false
forwardButton.enabled = false

在viewDidLoad()的約束條件添加代碼之後,創建並載入一個任務代碼之前,添加如下代碼。這句代碼使得這個類成為了loading屬性的監聽者。

webView.addObserver(self, forKeyPath: "loading", options: .New, context: nil)

添加下面的方法到類。這個方法將會在可監聽的屬性變化時執行。後退和前進按鈕將根據當前webview的狀態來決定是否可被點擊。

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer) {
    if (keyPath == "loading") {
        backButton.enabled = webView.canGoBack
        forwardButton.enabled = webView.canGoForward
    }
}

修改back(),forward()和reload()方法。

@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)
}

運行並測試這些按鈕。後退和前進按鈕開始時應該不可點擊。當你浏覽一個頁面時,後退按鈕應該可被點擊。當你後退時,前進按鈕應該可被點擊。點擊R按鈕,會重新加載頁面。

處理錯誤

我們不能保證用戶總是輸入正確地url,我們需要寫代碼來獲取這一錯誤並提示用戶。

首先修改類聲明,如下所示:

class ViewController: UIViewController, UITextFieldDelegate, WKNavigationDelegate

WKWebView有一個屬性navigationDelegate,接受一個實現WKNavigationDelegate協議的對象。這個協議提供了多種方法來處理導航事件,包括載入錯誤。

在init()底部添加如下代碼。通過下面的代碼,我們將這個類設置成了webview的navigation代理。

self.webView.navigationDelegate = self

接下來添加如下方法。這個代理方法將會在有錯誤發生時被調用。

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)
}

運行程序,輸入一個錯誤的url測試一下。

顯示進度

最後,我們將會添加一個進度顯示。

在storyboard文件中,在導航欄下方添加一個progress view。設置其top,right和left如下所示。

為progress view創建一個outlet。你應該會得到下面的代碼。

@IBOutlet weak var progressView: UIProgressView!

在ViewController中,替換西面的代碼

view.addSubview(webView)

view.insertSubview(webView, belowSubview: progressView)

在viewDidLoad()中創建和載入一個url任務之前添加下面的代碼,調用webview的addObserver方法。

webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil)

在observeValueForKeyPath()方法中的其他if語句之後添加如下代碼。

if (keyPath == "estimatedProgress") {
    progressView.hidden = webView.estimatedProgress == 1
    progressView.setProgress(Float(webView.estimatedProgress), animated: true)
}

這段代碼將會更新progressview的進度,如果加載完畢會隱藏progressview。

在類中添加如下代碼。這是一個WKNavigationDelegate的代理方法,將會在頁面載入完畢後執行。當一個任務完成後,我們使用它來重置progress view的進度。

func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {
    progressView.setProgress(0.0, animated: false)
}

運行程序,當網頁加載時,你將會看到一個藍色的進度條。

總結

我們已經了解了WebKit的基礎部分。我們看到如何添加一些和Safari相似的功能,如載入url,浏覽歷史,檢測錯誤,展示進度。在這個教程的第二部分,我們會深入了解如何將一個JavaScript注入網頁,來構建一個更強大的程序。

你可以通過這個鏈接來下載這個教程的實例代碼。

(本文為CocoaChina組織翻譯,本譯文權利歸譯者所有,未經允許禁止轉載。)

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved