Xcode 9 GM - WKWebView NSCoding 支持在以前的版本中被破坏

Xcode 9 GM - WKWebView NSCoding support was broken in previous versions

有谁知道如何用 Xcode 9 GM 修复这个错误?我正在开发一个使用 Xcode 8.3 制作的应用程序,部署目标是 iOS 9.3,我以前从未遇到过这个问题。我在这里或 Apple 论坛上找不到任何信息:(

编辑:当我将 WKWebView 放入界面生成器时出现此错误,如果我以编程方式使用它则不会。

编辑 2:好吧,这终于不是错误,请参阅下面 Quinn 的回答以了解有关此行为的更多信息。感谢他的解释。

UIWebView 在 iOS11 中已弃用,WKWebView 仅在 iOS11 中可用 - 这听起来像是 Xcode GM 中的错误。

这似乎是 Xcode 9 中的错误,并且也存在于测试版中。如果您通过故事板创建 WKWebView,您只会收到构建错误。如果您在相应的 ViewController class 文件中以编程方式创建 WKWebView,您应该能够在 iOS 11 以下的 iOS 版本上构建。 以下是 Apple 网站上提供的实现方法:

import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {

    var webView: WKWebView!

    override func loadView() {
        super.loadView()
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }
    override func viewDidLoad() {
        super.viewDidLoad()

        let myURL = URL(string: "https://www.apple.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }}

然后您应该能够像往常一样实现 WKWebView 功能。

来源:https://developer.apple.com/documentation/webkit/wkwebview

错误是正确的行为,而不是 Xcode 9 中的错误。虽然 WKWebView 是在 iOS 8 中引入的,但 -[WKWebView initWithCoder:] 中存在一个错误,仅在 Xcode 中修复iOS 11,它总是在运行时崩溃,因此无法在 Interface Builder 中配置一个。

https://bugs.webkit.org/show_bug.cgi?id=137160

它不是允许开发人员在 IB 中构建会在运行时损坏的东西,而是构建错误。这是一个不方便的限制,因为 iOS 11 最近才发布,但实际上没有其他好的选择。

旧部署目标的解决方法是继续在代码中添加 WKWebView,如 @fahad-ashraf 在他的回答中所述:

https://developer.apple.com/documentation/webkit/wkwebview

如果你想实现一个 自定义 UIViewController 另外你可以通过故事板制作一个“容器”,例如 webViewContainer :

import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
    @IBOutlet weak var webViewContainer: UIView!
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let webConfiguration = WKWebViewConfiguration()
        let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: self.webViewContainer.frame.size.width, height: self.webViewContainer.frame.size.height))
        self.webView = WKWebView (frame: customFrame , configuration: webConfiguration)
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.webViewContainer.addSubview(webView)
        webView.topAnchor.constraint(equalTo: webViewContainer.topAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: webViewContainer.rightAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: webViewContainer.leftAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: webViewContainer.bottomAnchor).isActive = true
        webView.heightAnchor.constraint(equalTo: webViewContainer.heightAnchor).isActive = true
        webView.uiDelegate = self
        
        let myURL = URL(string: "https://www.apple.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

我遇到了同样的问题,但如果我们以编程方式添加 WKWebView 就可以解决。

  1. 在情节提要中做任何你想做的设计,但要为 WKWebView 留出空间,在该区域拖放一个视图并将其命名为 webViewContainer 并声明这两个属性,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
    
  2. 现在像这样创建和添加 webView:

    -(instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        self.webView = [self createWebView];
        self = [super initWithCoder:aDecoder];
        return self;
    }
    

    createWebView 函数声明为,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
    
  3. 现在将这个新创建的 webView 添加到您的 containerView 中,如下所示:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
    
  4. 最后,像这样加载你的Url,

    -(void)webViewLoadUrl:(NSString *)stringUrl
    {
         NSURL *url = [NSURL URLWithString:stringUrl];
         NSURLRequest *request = [NSURLRequest requestWithURL:url];
         [self.webView loadRequest:request];
    }
    

感谢阅读本文。

如果您从较旧的目标移至 iOS 11.0,但仍然出现此错误,请使用以下解决方案。

  1. Go to Storyboard (Main.storyboard), click on any Scene.
  2. Select 'File Inspector' which is the right side property window of Xcode
  3. Change 'Builds for' value to 'iOS 11.0 and Later'
  4. Compile and Build

WebKit 是在 iOS 8 中引入的,但发布时出现错误导致运行时崩溃,如果您使用 Xcode 9/10,您的项目配置支持小于 iOS 11 并且如果您尝试使用界面生成器添加 WKWebView。 Xcode 立即显示编译时错误。

WKWebView before iOS 11.0(NSCoding 支持在以前的版本中被破坏)

虽然WKWebView是在iOS8中引入的,但在-[WKWebView initWithCoder:]中有一个错误,仅在[=中修复37=]11.

解决方案是您必须通过代码添加 WKWebView(仅当您支持以下 iOS 11 时)。这听起来确实很奇怪。

另一个解决方案 是将选项的 Interface Builder Document Builds 更改为 iOS 11 及更高版本(如果您要从旧目标迁移到 iOS 11 并且仍然出现相同的错误)。

//对于Swift

import WebKit

class ViewController: UIViewController {
var webView: WKWebView!

// MARK:- WebView Configure
override func loadView() {
    let webConfig = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfig)
    view = webView
}


override func viewDidLoad() {
    super.viewDidLoad()
    // call urlrequest fun
    loadURLRequest()
}

//MARK:- Webview URLRequest
func loadURLRequest()  {
    let urlString = "https://www.google.com"
    let url = URL(string: urlString)
    let urlRequest = URLRequest(url: url!)
    webView.load(urlRequest)
}
}

// 对于 Objective C

#import <WebKit/WebKit.h>

@interface ViewController ()<WKNavigationDelegate,WKUIDelegate>{
WKWebView *webView;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
    
NSURL *url = [[NSURL alloc] initWithString: @"https://www.google.com"];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
    [webView loadRequest: request];
}


- (void)loadView {
[super loadView];

WKWebViewConfiguration *configu = [[WKWebViewConfiguration alloc] init];
webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configu];
webView.UIDelegate = self;
self.view = webView;
}

@end

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    
    @IBOutlet weak var webViewContainer: UIView!
    private var webView: WKWebView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        addWebView()
        
        let myURL = URL(string: "https://www.apple.com")
        if let myURL = myURL {
            let myRequest = URLRequest(url: myURL)
            webView?.load(myRequest)
        }
    }
    
    private func addWebView() {
        let webConfiguration = WKWebViewConfiguration()
        let size = CGSize.init(width: 0.0, height: self.webViewContainer.frame.size.height)
        let customFrame = CGRect.init(origin: CGPoint.zero, size: size)
        self.webView = WKWebView (frame: customFrame, configuration: webConfiguration)
        if let webView = self.webView {
            webView.translatesAutoresizingMaskIntoConstraints = false
            self.webViewContainer.addSubview(webView)
            webView.topAnchor.constraint(equalTo: webViewContainer.topAnchor).isActive = true
            webView.rightAnchor.constraint(equalTo: webViewContainer.rightAnchor).isActive = true
            webView.leftAnchor.constraint(equalTo: webViewContainer.leftAnchor).isActive = true
            webView.bottomAnchor.constraint(equalTo: webViewContainer.bottomAnchor).isActive = true
            webView.heightAnchor.constraint(equalTo: webViewContainer.heightAnchor).isActive = true
            webView.uiDelegate = self
        }
    }
}

你可以设置 IPHONEOS_DEPLOYMENT_TARGET >= 11