177

Does anyone know how to fix this error with Xcode 9 GM? I'm working on an app made with Xcode 8.3, the deployment target is for iOS 9.3 and I never had this problem before. I don't find any information here or on Apple forums yet :(

Edit: This error came when I put a WKWebView into interface builder, not if I use it programmatically.

See picture WKWebView Error

Edit 2: Well, it's finally not a bug, see Quinn's answer below to have more information about this behavior. Thanks to him for the explanation.

Mehdi Chennoufi
  • 2,193
  • 2
  • 11
  • 16
  • 1
    See my answer below. This is not a bug in Xcode 9; without this build error, you would instead get a crash in -initWithCoder: at runtime prior to iOS 11. – Quinn Taylor Oct 09 '17 at 14:59
  • 1
    I just change my deployment target to 11 – wei May 16 '18 at 21:24
  • This should be a comment on Kampai's answer, but I don't have enough reputation points to comment. Besides explicit iOS versions the 'Builds for' dropdown in the 'File Inspector' also contains the **Deployment Target (..)** option. I prefer managing versions at a single place if possible and wanted to change the build target anyway. I was fully confused it still said **Deployment Target (9.3)** although I changed the corresponding entry in the general settings to **11.0**. **Restart** of XCode (11.3.1) was necessary to make everything work as expected, the option 'Deployment Target (11.0)' was – ThomasB May 08 '20 at 15:45

10 Answers10

173

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

Quinn Taylor
  • 44,553
  • 16
  • 113
  • 131
  • 3
    Hi Quinn, I believe the man who works at Apple :-) I also found your bug report about that : https://lists.webkit.org/pipermail/webkit-unassigned/2014-September/640090.html Thank you for your answer it's really surprising for new developers like me when we encountering a behavior like that. Thanks again. – Mehdi Chennoufi Oct 10 '17 at 18:29
  • 3
    what if we want to support in ios10 also?. in my app i need to support ios 10 also.How can we solve this issue? – Kalikanth040494 Oct 11 '18 at 13:38
  • just curious why did it take Apple until iOS 11 to figure out a fix? – Eman May 24 '19 at 18:53
100

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

Makalele
  • 7,431
  • 5
  • 54
  • 81
Fahad Ashraf
  • 1,138
  • 1
  • 6
  • 6
  • 5
    don't forget `super.loadView()` – albirrojo7 Mar 01 '18 at 14:37
  • `super.loadView()` has to be at the beginning. Without it, nothing shows. – Makalele Mar 27 '18 at 09:27
  • hi :), do you know how I can set the constraints of this `webview` to below my NavigationBar? This solution of you works but it covers the whole screen. – Abed Naseri Jun 04 '18 at 17:24
  • @AbedNaseri i think you don't need to put constraints... you can instantiate storyboard and then self.navigationController?.pushViewController(youVC, animated: true) . – xhinoda Jul 06 '18 at 13:14
  • programmatically set the frame / constrain is the key. ps. I didn't use super.loadView() – Mia Aug 23 '21 at 10:01
64

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)
    }
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • Thank you so much, it's really help. It's a bug know by Apple – Sébastien REMY Nov 06 '17 at 19:30
  • 1
    Worked! tested in iOS 11 and swift 4.1 – Alwin May 16 '18 at 09:32
  • 2
    If you are getting the error `[LayoutConstraints] Unable to simultaneously satisfy constraints`, don't forget the line `webView.translatesAutoresizingMaskIntoConstraints = false`. If you leave it set to true, it will create a whole set of constraints for your `webView` automatically which will conflict with the constraints you add programmatically. [Apple Docs](https://developer.apple.com/documentation/uikit/uiview/1622572-translatesautoresizingmaskintoco). – mogelbuster Oct 15 '18 at 16:49
  • 1
    Just change the following line From: `let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.webViewContainer.frame.size.height))` To: `let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: self.webViewContainer.frame.size.width, height: self.webViewContainer.frame.size.height))` – Syed Faizan Ahmed Aug 26 '20 at 10:38
62

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

Kampai
  • 22,848
  • 21
  • 95
  • 95
  • 2
    @VyachaslavGerchicov: I don't know about you, but in the industry, we do have such older projects which need to be converted to newer tech. So many facing the same problem. I already mentioned in the answer that "if you are moved from older target". Don't think of only one case. – Kampai Oct 31 '18 at 05:35
  • 1
    This works for me thanks for pointing this annoying IB setup. The warning is gone right away. Actually, I think this more practical and should be accepted answer. Agree with @Kampai, actually, we are forced to move to the new version of iOS, since the Apple keep changing their fundamental frameworks – infinity_coding7 Nov 19 '18 at 17:23
  • After doing it when running on simulator with iOS 10.x app crashes. – Ramis May 13 '19 at 14:49
  • @Ramis: I was doing it for iOS 10, I never got app crash, what was the crash log? – Kampai May 14 '19 at 06:38
  • @Kampai: Currently I can not remember exact crash log. So can not answer to your question. – Ramis May 14 '19 at 06:42
  • 1
    Simplest solution for fixing this issue. Thanks! – Jerry Chong Jul 15 '19 at 03:37
  • For those considering building for iOS 11 and above, as of August 6, 2019 only 3% of users are using < iOS 11. – Bikeboy Aug 14 '19 at 18:06
18

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.

Najam
  • 1,129
  • 11
  • 32
5

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

Mr.Javed Multani
  • 12,549
  • 4
  • 53
  • 52
3

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

ShigaSuresh
  • 1,598
  • 17
  • 19
0
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
        }
    }
}
Deviyani Swami
  • 749
  • 8
  • 17
0

You can just set IPHONEOS_DEPLOYMENT_TARGET >= 11

[Deployment Target]

yoAlex5
  • 29,217
  • 8
  • 193
  • 205
-5

UIWebView is deprecated in iOS11 and WKWebView works only in iOS11 - this sounds like a bug in Xcode GM.

pawel221
  • 977
  • 1
  • 7
  • 9