Xcode 9 GM - La prise en charge de WKWebView NSCoding était interrompue dans les versions précédentes


155

Quelqu'un sait-il comment corriger cette erreur avec Xcode 9 GM? Je travaille sur une application réalisée avec Xcode 8.3, la cible de déploiement est pour iOS 9.3 et je n'ai jamais eu ce problème auparavant. Je ne trouve pas encore d'informations ici ou sur les forums Apple :(

Edit: Cette erreur est survenue lorsque j'ai mis un WKWebView dans le générateur d'interface, pas si je l'utilise par programme.

Voir l'image Erreur WKWebView

Edit 2: Eh bien, ce n'est finalement pas un bug, voir la réponse de Quinn ci-dessous pour avoir plus d'informations sur ce comportement. Merci à lui pour l'explication.


1
Voir ma réponse ci-dessous. Ce n'est pas un bogue dans Xcode 9; sans cette erreur de construction, vous auriez à la place un plantage dans -initWithCoder: à l'exécution avant iOS 11.
Quinn Taylor

1
Je viens de changer mon objectif de déploiement en 11
wei

Réponses:


160

L'erreur est un comportement correct, et non un bogue dans Xcode 9. Bien que WKWebView ait été introduit dans iOS 8, il y avait un bogue -[WKWebView initWithCoder:]qui n'a été corrigé que dans iOS 11, qui plantait toujours à l'exécution et empêchait donc d'en configurer un dans Interface Builder.

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

Plutôt que de permettre aux développeurs de créer quelque chose dans IB qui serait cassé au moment de l'exécution, il s'agit d'une erreur de construction. C'est une limitation gênante puisque iOS 11 n'a été publié que récemment, mais il n'y a vraiment pas d'autre bonne option.

La solution de contournement pour les anciennes cibles de déploiement est de continuer à ajouter le WKWebView dans le code, comme @ fahad-ashraf déjà décrit dans sa réponse:

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


3
Salut Quinn, je crois que l'homme qui travaille chez Apple :-) J'ai aussi trouvé votre rapport de bogue à ce sujet: lists.webkit.org/pipermail/webkit-unassigned/2014-September/… Merci pour votre réponse c'est vraiment surprenant pour nouveau les développeurs comme moi quand nous rencontrons un comportement comme celui-là. Merci encore.
Mehdi Chennoufi

Je vous remercie! C'était utile.
ssowri1

2
et si nous voulons prendre en charge dans ios10 également ?. dans mon application, je dois également prendre en charge iOS 10. Comment pouvons-nous résoudre ce problème?
Kalikanth040494

juste curieux de savoir pourquoi a-t-il fallu à Apple jusqu'à iOS 11 pour trouver un correctif?
Eman

96

Cela semble être un bogue dans Xcode 9 et était également présent dans les bêtas. Vous n'obtiendrez l'erreur de construction que si vous créez un WKWebView via le storyboard. Si vous créez progressivement le WKWebView dans le fichier de classe ViewController correspondant, vous devriez pouvoir construire sur des versions iOS inférieures à iOS 11. Voici l'approche donnée sur le site Web d'Apple pour savoir comment y parvenir:

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

Vous devriez alors être en mesure d'implémenter la fonctionnalité WKWebView comme vous le feriez normalement.

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


5
n'oubliez passuper.loadView()
albirrojo7

super.loadView()doit être au début. Sans cela, rien ne se voit.
Makalele

salut :), savez-vous comment je peux définir les contraintes de ceci webviewsous ma barre de navigation? Cette solution de vous fonctionne mais elle couvre tout l'écran.
Abed Naseri le

@AbedNaseri je pense que vous n'avez pas besoin de mettre de contraintes ... vous pouvez instancier le storyboard puis self.navigationController? .PushViewController (youVC, animated: true).
xhinoda

58

Si vous souhaitez réaliser un customUIViewController avec d'autres composants en plus vous pouvez créer un "container" à travers le storyboard appelé par exemple 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: 0.0, 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)
    }

Merci beaucoup, c'est vraiment une aide. C'est un bug connu par Apple
Sébastien REMY

1
Travaillé! testé sous iOS 11 et swift 4.1
Alwin

2
Si vous obtenez l'erreur [LayoutConstraints] Unable to simultaneously satisfy constraints, n'oubliez pas la ligne webView.translatesAutoresizingMaskIntoConstraints = false. Si vous laissez la valeur true, cela créera webViewautomatiquement tout un ensemble de contraintes qui entreront en conflit avec les contraintes que vous ajoutez par programme. Documents Apple .
mogelbuster

51

Si vous êtes déplacé de l'ancienne cible vers iOS 11.0 et que vous obtenez toujours cette erreur, utilisez la solution ci-dessous.

  1. Allez dans Storyboard (Main.storyboard), cliquez sur n'importe quelle scène.
  2. Sélectionnez 'File Inspector' qui est la fenêtre de propriétés de droite de Xcode
  3. Remplacez la valeur " Builds for " par " iOS 11.0 et versions ultérieures ".
  4. Compiler et construire

entrez la description de l'image ici


2
@VyachaslavGerchicov: Je ne sais pas pour vous, mais dans l'industrie, nous avons des projets plus anciens qui doivent être convertis à de nouvelles technologies. Tant de personnes confrontées au même problème. J'ai déjà mentionné dans la réponse que "si vous êtes déplacé d'une cible plus ancienne". Ne pensez pas à un seul cas.
Kampai

1
Cela fonctionne pour moi merci d'avoir pointé cette configuration IB ennuyeuse. L'avertissement est parti tout de suite. En fait, je pense que cette réponse est plus pratique et devrait être acceptée. D'accord avec @Kampai, en fait, nous sommes obligés de passer à la nouvelle version d'iOS, puisque Apple continue de changer ses cadres fondamentaux
infinity_coding7

Après l'avoir fait lors de l'exécution sur le simulateur avec l'application iOS 10.x se bloque.
Ramis

@Ramis: Je le faisais pour iOS 10, je n'ai jamais eu de crash d'application, quel était le journal des plantages?
Kampai

1
La solution la plus simple pour résoudre ce problème. Merci!
Jerry Chong

18

J'ai rencontré le même problème mais il peut être résolu si nous ajoutons résolu WKWebView par programme.

  1. Faites la conception que vous voulez faire dans le storyboard mais laissez la place à WKWebView , dans cette zone, faites glisser et déposez une vue et nommez-la webViewContainer et déclarez ces deux propriétés,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
  2. Maintenant, créez et ajoutez webView comme ceci:

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

    La fonction createWebView est déclarée comme,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
  3. Ajoutez maintenant cette webView nouvellement créée à votre containerView, comme ceci:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
  4. Enfin, chargez simplement votre URL comme ceci,

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

Merci d'avoir lu ceci.


3

WebKit a été introduit dans iOS 8 mais il a été publié avec une erreur qui a provoqué un crash d'exécution.Si vous utilisez Xcode 9/10 , la configuration de votre projet prend en charge moins d' iOS 11 et si vous essayez d'ajouter WKWebView à l'aide du générateur d'interface. Xcode affiche immédiatement une erreur de compilation.

WKWebView avant iOS 11.0 (la prise en charge de NSCoding était interrompue dans la version précédente)

Bien que WKWebView ait été introduit dans iOS 8 , il y avait un bogue dans - [WKWebView initWithCoder:] qui n'a été corrigé que dans iOS 11 .

entrez la description de l'image ici

La résolution est que vous devez ajouter WKWebView via le code (uniquement si vous prenez en charge sous iOS 11). Cela semble en fait étrange.

Une autre solution consiste à modifier les versions de document Interface Builder pour l'option vers iOS 11 et versions ultérieures (si vous migrez d'une cible plus ancienne vers iOS 11 et que vous obtenez toujours la même erreur).


1

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

// Pour l'objectif 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

entrez la description de l'image ici


0

Cela devrait être un commentaire sur la réponse de Kampai, mais je n'ai pas assez de points de réputation pour commenter.

Outre les versions iOS explicites, la liste déroulante «Construit pour» dans «l'inspecteur de fichiers» contient également l' option Cible de déploiement (..) . Je préfère gérer les versions à un seul endroit si possible et je voulais quand même changer la cible de construction. J'étais complètement confus, il disait toujours cible de déploiement (9.3) bien que j'aie changé l'entrée correspondante dans les paramètres généraux en 11.0 .

Le redémarrage de XCode (11.3.1) était nécessaire pour que tout fonctionne comme prévu, l'option 'Deployment Target (11.0)' était disponible (et 9.3 avait disparu). Après la sélection, tout a fonctionné comme prévu.


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

-5

UIWebView est obsolète dans iOS11 et WKWebView fonctionne uniquement dans iOS11 - cela ressemble à un bogue dans Xcode GM.


Oui. La seule solution de contournement que j'ai trouvée si vous souhaitez déployer sur la version précédente d'iOS est d'ajouter votre WKWebView par programme.
Mehdi Chennoufi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.