如何迁移到WKWebView?

73

我正在尝试了解如何在iOS8中利用新的WKWebView,但找不到太多信息。我已经阅读了以下内容:

http://developer.telerik.com/featured/why-ios-8s-wkwebview-is-a-big-deal-for-hybrid-development/ http://nshipster.com/wkwebkit/

但是这会影响现有的应用程序吗?普通的UiWebView是否会获得来自nitro JavaScript引擎的加速,还是我们需要进行更改?我们如何处理向后兼容性?

我能找到的所有代码和示例都使用Swift,这是必须的吗?

感谢您对此事提供任何帮助!


也许这会对您有所帮助:http://floatlearning.com/2014/12/one-webview-to-rule-them-all/ - koen
http://blog.initlabs.com/post/100113463211/wkwebview-vs-uiwebview - jose920405
请看我的答案,将其添加为Swift 3.0中的子视图。https://dev59.com/6ZTfa4cB1Zd3GeqPPlxm#41205568 - Fay007
这可能会有所帮助- https://dev59.com/nabja4cB1Zd3GeqPaAZN - Krunal
9个回答

68

UIWebView仍将继续与现有应用程序一起使用。WKWebView从开始提供,只有WKWebView具有Nitro JavaScript引擎。

要利用旧应用程序中的更快JavaScript引擎,您必须进行代码更改以使用WKWebView而不是UIWebView。对于及更早版本,您必须继续使用UIWebView,因此您可能需要检查,然后应用WKWebView方法/委托方法,并回退到UIWebView方法以适用于及更早版本。还没有WKWebView的Interface Builder组件(尚未),因此您必须以编程方式实现WKWebView

您可以在Objective-C中实现WKWebView,这里是启动WKWebView的简单示例:

WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:theConfiguration];
webView.navigationDelegate = self;
NSURL *nsurl=[NSURL URLWithString:@"http://www.apple.com"];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[webView loadRequest:nsrequest];
[self.view addSubview:webView];
WKWebView 的渲染性能在 WebGL 游戏和运行复杂 JavaScript 算法时表现突出,如果您只是使用 webview 加载简单的 HTML 或网站,则可以继续使用 UIWebView

这里有一个测试 app,它可以使用 UIWebViewWKWebView 打开任何网站,并且您可以比较性能,然后决定升级您的应用程序以使用 WKWebViewhttps://itunes.apple.com/app/id928647773?mt=8&at=10ltWQ

enter image description here


另外需要考虑的是,在iOS 8上使用WKWebView技术并在iOS 7上回退到UIWebView可能会遇到AppStore验证问题。https://dev59.com/fV8e5IYBdhLWcg3wS425 - Onnmir
只是一个提示:需要在 info.plist 中使用 NSAppTransportSecurityNSAllowsArbitraryLoads 才能正常工作。 - Carlos Irano
2
现在已经不可能使用UIWebView,您无法将使用它的应用程序推送到商店。 - foufrix

55

以下是我从 UIWebView 迁移到 WKWebView 的方式。

注意:没有像 UIWebView 那样的属性可以拖放到你的 storyboard 上,你必须通过编程实现它。

确保在你的头文件中导入 WebKit/WebKit.h

这是我的头文件:

#import <WebKit/WebKit.h>

@interface ViewController : UIViewController

@property(strong,nonatomic) WKWebView *webView;
@property (strong, nonatomic) NSString *productURL;

@end

这是我的实现文件:

#import "ViewController.h"

@interface ViewController ()

@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.productURL = @"http://www.URL YOU WANT TO VIEW GOES HERE";

    NSURL *url = [NSURL URLWithString:self.productURL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    _webView = [[WKWebView alloc] initWithFrame:self.view.frame];  
    [_webView loadRequest:request];
    _webView.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    [self.view addSubview:_webView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

2
如何加载本地文件?我尝试了,但页面上没有显示任何内容。还有像UIWebview这样的委托方法是什么?例如:didloadRequest。 - nr5
1
只需注意: 需要在 info.plist 中使用 NSAppTransportSecurityNSAllowsArbitraryLoads 才能正常工作。 - Carlos Irano
我复制了你上面的代码。我尝试了几个在浏览器中通常有效的URL,但是视图中没有显示任何内容。可能缺少什么? - John Wooten

21

步骤 :1ViewController.swift 中导入 webkit

import WebKit

步骤:2 声明 webView 变量。

var webView : WKWebView!

第三步:添加WKNavigationDelegate代理

class ViewController: UIViewController , WKNavigationDelegate{

步骤:4ViewDidLoad 中添加代码。

let myBlog = "https://iosdevcenters.blogspot.com/"
let url = NSURL(string: myBlog)
let request = NSURLRequest(URL: url!)

// init and load request in webview.
webView = WKWebView(frame: self.view.frame)
webView.navigationDelegate = self
webView.loadRequest(request)
self.view.addSubview(webView)
self.view.sendSubviewToBack(webView)

步骤:5 编辑info.plist,添加

<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>google.com</key>
<dict>
    <key>NSExceptionAllowsInsecureHTTPLoads</key>
    <true/>
    <key>NSIncludesSubdomains</key>
    <true/>
</dict>
</dict>

1
如何在WebView中保存Cookie - kirti Chavda
1
只需要注意,在 info.plist 中使用 NSAppTransportSecurityNSAllowsArbitraryLoads 才能正常工作。 - Carlos Irano
@KiritModi,如何在wkwebview中保存cookie,我遇到了注销问题(会话过期),请评论。 - Shobhakar Tiwari
@ShobhakarTiwari:请查看此链接 https://dev59.com/Tl8d5IYBdhLWcg3wpzr4 - Kirit Modi
@kirtimali,你不能在iOS 10及以下版本的WKWebView中读取HTTP Only Cookie。但是在iOS 11中,苹果引入了新的API来从WKWebView中读取Cookie。https://developer.apple.com/documentation/webkit/wkhttpcookiestore?changes=latest_minor - Chetan Dobariya

10

Swift不是必需的,使用Objective-C也可以正常工作。UIWebView将继续得到支持,所以如果您想花时间迁移,就没有必要赶快行动。但是,它将无法获得WKWebView的Javascript和滚动性能增强功能。

为了向后兼容,我的视图控制器有两个属性:一个是UIWebView,另一个是WKWebView。只有当类存在时,我才会使用WKWebView:

if ([WKWebView class]) {
    // do new webview stuff
} else {
    // do old webview stuff
}

我曾经使用UIWebViewDelegate,现在我也将它设为WKNavigationDelegate,并创建了必要的方法。


使用[WKWebView类]进行运行时检查是一个非常好的点,比检查iOS版本号要好得多。 - JonSlowCN
请注意,您能否提及从哪个版本开始wkwebview不可用?看起来它从iOS 8开始可用,因此不需要添加此检查和冗余代码。 - Muhammad Shauket

8

根据 苹果文档,WkWebView比UIWebview更快更可靠。这里是我发布的WkWebViewController。

import UIKit
import WebKit

class WebPageViewController: UIViewController,UINavigationControllerDelegate,UINavigationBarDelegate,WKNavigationDelegate{

    var webView: WKWebView?
    var webUrl="http://www.nike.com"

    override func viewWillAppear(animated: Bool){
        super.viewWillAppear(true)
        navigationController!.navigationBar.hidden = false

    }
    override func viewDidLoad()
    {
        /* Create our preferences on how the web page should be loaded */
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = false

        /* Create a configuration for our preferences */
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences

        /* Now instantiate the web view */
        webView = WKWebView(frame: view.bounds, configuration: configuration)

        if let theWebView = webView{
            /* Load a web page into our web view */
            let url = NSURL(string: self.webUrl)
            let urlRequest = NSURLRequest(URL: url!)
            theWebView.loadRequest(urlRequest)
            theWebView.navigationDelegate = self
            view.addSubview(theWebView)

        }


    }
    /* Start the network activity indicator when the web view is loading */
    func webView(webView: WKWebView,didStartProvisionalNavigation navigation: WKNavigation){
            UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    }

    /* Stop the network activity indicator when the loading finishes */
    func webView(webView: WKWebView,didFinishNavigation navigation: WKNavigation){
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    }

    func webView(webView: WKWebView,
        decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse,decisionHandler: ((WKNavigationResponsePolicy) -> Void)){
            //print(navigationResponse.response.MIMEType)
            decisionHandler(.Allow)

    }
    override func didReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
    }

}

5

在iOS 8中使用Swift编写WKWebView。

现在整个ViewController.swift文件看起来像这样:

import UIKit
import WebKit

class ViewController: UIViewController {

    @IBOutlet var containerView : UIView! = nil
    var webView: WKWebView?

    override func loadView() {
        super.loadView()

        self.webView = WKWebView()
        self.view = self.webView!
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        var url = NSURL(string:"http://www.kinderas.com/")
        var req = NSURLRequest(URL:url)
        self.webView!.loadRequest(req)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

2

使用一些设计模式,您可以混合使用UIWebView和WKWebView。 关键是设计一个独特的浏览器界面。 但是您应该更加关注您的应用程序的当前功能, 例如:如果您的应用程序使用NSURLProtocol来增强网络能力,则使用WKWebView您将无法执行相同的操作。因为NSURLProtocol仅对当前进程产生影响,而WKWebView使用多进程架构,网络工作在单独的进程中。


1

为了加速,您需要使用WKWebView,它在iOS8中作为WebKit框架的一部分提供。

如果需要向后兼容,您需要在iOS7及更早版本中使用UIWebView。

我设置了一个小代码来为新的WKWebView提供UIViewController框架。它可以通过cocoapods安装。请查看这里:

STKWebKitViewController on github


0

Swift 4

    let webView = WKWebView()   // Set Frame as per requirment, I am leaving it for you
    let url = URL(string: "http://www.google.com")!
    webView.load(URLRequest(url: url))
    view.addSubview(webView)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接