转自:http://www.cocoachina.com/ios/20150203/11089.html http://www.cocoachina.com/ios/20150205/11108.html
(原文: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框架。
1
|
import WebKit
|
将下面的变量加入到类中
1
|
var
webView: WKWebView
|
将下面的方法加入到类中。它将会初始化webview并设置其frame为0.稍后我们会使用自动布局(auto layout)来给webview添加约束,这样这个webview就能在任何苹果设备和任何方向上正常工作了。
1
2
3
4
|
required init(coder aDecoder: NSCoder) {
self.webView = WKWebView(frame: CGRectZero)
super
.init(coder: aDecoder)
}
|
在viewDidLoad()底部,添加如下语句。这样这个webView就被添加到主视图了。
1
|
view.addSubView(webView)
|
接下来,在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])
|
在此处,我们首先禁止了自动约束。然后我们对webview的宽和高添加了约束。这样webview就会和它的superview拥有一样的宽和高了。
在程序启动时,我们将会打开一个默认页。然后我们添加一个textfield控件,这样用户就能输入自己想浏览的地址了。在viewDidLoad()底部添加如下代码
1
2
3
|
let request = NSURLRequest(URL:url!)
webView.loadRequest(request)
|
运行程序。它将会加载Appcoda的主页。注意当你滑动页面的时候在导航栏下面也能看到模糊的网页,我们将禁止这样。首先打开 Main.storyboard选择网页显示的ViewController。在属性检查(也就是右边的第四栏中)将Extend Edges中得Under Top Bars去掉勾选。再次运行程序,我们就会发现导航栏已经没有了毛玻璃效果,而且我们也不能看见它下面的网页内容了。
接下来让我们添加给用户输入URL的控件。
在storyboard文件中,给向导航栏中拖放一个view。在属性检查(右边第四栏)中,设置其背景色为透明(clear color)。因为我们无法给导航栏中的view添加约束,我们将会以代码的形式调整其大小。
1
|
@IBoutlet weak
var
barView: UIView!
|
在viewDidLoad()的super.viewDidLoad()之后添加如下代码
1
|
barView.frame = CGRect(x:0, y: 0, width: view.frame.width, height: 30)
|
这段代码设置了barView的大小。
将下面的方法添加到类
1
2
3
|
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。你应会看到如下代码。
1
|
@IBOutlet weak
var
urlField: UITextField!
|
我们希望viewcontroller能成为UITextFieldDelegate的代理,在storyboard的Document Outline中,按下control然后将textfield拖放到viewcontroller,然后在弹出视图选择delegate。
选择textfield控件,在属性检查(右边第四栏)设置如下属性。
-
Clear Button:Appears while editing
-
Correction: NO
-
Keyboard Type:URL
-
Return Key:Go
在类声明部分添加实现UITextFieldDelegate代码。
1
|
class ViewController: UIViewController, UITextFieldDelegate
|
接下来添加如下UITextFieldDelegate代码
1
2
3
4
5
|
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。
1
|
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。你应该会得到如下代码
1
2
3
|
@IBOutlet weak
var
backButton: UIBarButtonItem!
@IBOutlet weak
var
forwardButton: UIBarButtonItem!
@IBOutlet weak
var
reloadButton: UIBarButtonItem!
|
然后为每个按钮依次分别创建back,forward和reload方法。将每个action的Type更改为UIBarButtonItem。你应该会得到如下代码。
1
2
3
4
5
6
7
8
|
@IBAction func back(sender: UIBarButtonItem) {
}
@IBAction func forward(sender: UIBarButtonItem) {
}
@IBAction func reload(sender: UIBarButtonItem) {
}
|
在viewDidLoad()的底部添加如下代码。我们不希望后退和前进按钮在App被启动时就可点击。
1
2
|
backButton.enabled =
false
forwardButton.enabled =
false
|