Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

The error is correct behavior, and not a bug in Xcode 9. Although WKWebView was introduced in iOS 8, there was a bug in -[WKWebView initWithCoder:] that was only fixed in iOS 11, which always crashed at runtime and thus prevented configuring one within Interface Builder.

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

Rather than allow developers to build something in IB that would be broken at runtime, it is a build error. It's an inconvenient limitation since iOS 11 was only recently released, but there's really no other good option.

The workaround for older deployment targets is to continue to add the WKWebView in code, as @fahad-ashraf already described in his answer:

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


This seems to be a bug in Xcode 9 and was also present in the betas. You will only get the build error if you are creating a WKWebView through the storyboard. If you progmatically create the WKWebView in the corresponding ViewController class file, you should be able to build on iOS versions below iOS 11. Here is the approach given on Apple's website for how to accomplish this:

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

You should then be able to implement WKWebView functionality as you normally would.

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


If you want to realize a custom UIViewController with other components in addition you can make a "container" through the storyboard called for example 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)
    }

If you are moved from older target to iOS 11.0 and still you are getting this error, then use below solution.

  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

enter image description here


I have faced the same issue but it can be tackle if we add WKWebView programmatically.

  1. Do whatever design you want to make in storyboard but leave the room for WKWebView, in that area drag & drop a view and name it as webViewContainer and declare these two properties,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
    
  2. Now create and add webView like this:

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

    createWebView function is declared as,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
    
  3. Now add this newly created webView to your containerView, like this, :

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
    
  4. Finally, just load your Url like this,

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

Thanks for reading this.


WebKit was introduced in iOS 8 but it was released with an error which caused in a runtime crash, If you are using Xcode 9/10, your project configuration support less than iOS 11 and if you are trying to add WKWebView using interface builder. Xcode immediately shows a compile-time error.

WKWebView before iOS 11.0 (NSCoding Support was broken in the previous version)

Although WKWebView was introduced in iOS 8, there was a bug in –[WKWebView initWithCoder:] that was only fixed in iOS 11.

enter image description here

Resolution is you must add WKWebView through code (Only if you are supporting below iOS 11). That actually sounds strange.

Another solution is to change the Interface Builder Document Builds for the option to iOS 11 and later (If you’re migrating from older target to iOS 11 and still getting the same error).


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

// For 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

enter image description here