web-dev-qa-db-fra.com

WKWebView dans Interface Builder

Il semble que les modèles d'objet IB de XCode 6 bêta créent encore des objets de style ancien (UIWebView pour iOS et WebView pour OSX). Espérons que Apple les mettra à jour pour le WebKit moderne, mais jusque-là, quel est le meilleur moyen de créer WKWebViews dans Interface Builder? Devrais-je créer une vue de base (UIView ou NSView) et attribuer son type WKWebView? La plupart des exemples que je trouve en ligne l’ajoute par programme à une vue conteneur; est-ce mieux pour une raison quelconque?

93
Adam Fox

Vous avez raison, cela ne semble pas fonctionner. Si vous regardez dans les en-têtes, vous verrez:

- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;

ce qui implique que vous ne pouvez pas en instancier un à partir d'une plume.

Vous devrez le faire à la main dans viewDidLoad ou loadView.

69
EricS

Comme certains l'ont souligné, à partir de Xcode 6.4, WKWebView n'est toujours pas disponible sur Interface Builder. Cependant, il est très facile de les ajouter via un code.

J'utilise simplement cela dans mon ViewController. Ignorer le constructeur d'interface

import UIKit
import WebKit

class ViewController: UIViewController {

    private var webView: WKWebView?

    override func loadView() {
        webView = WKWebView()

        //If you want to implement the delegate
        //webView?.navigationDelegate = self

        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if let url = URL(string: "https://google.com") {
            let req = URLRequest(url: url)
            webView?.load(req)
        }
    }
}
65
Johan

Info.plist

ajoutez dans votre paramètre de sécurité de transport Info.plist

 <key>NSAppTransportSecurity</key>
 <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
 </dict>

Xcode 9.1+

Utilisation du constructeur d'interface

Vous pouvez trouver l'élément WKWebView dans la bibliothèque d'objets.

enter image description here

Ajouter une vue par programme avec Swift 5

let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true

Ajouter une vue par programme avec Swift 5 (échantillon complet)

import UIKit
import WebKit

class ViewController: UIViewController {

    private weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        initWebView()
        webView.loadPage(address: "http://Apple.com")
    }

    private func initWebView() {
        let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
        view.addSubview(webView)
        self.webView = webView
        webView.translatesAutoresizingMaskIntoConstraints = false
        webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
    }
}

extension WKWebView {
    func loadPage(address url: URL) { load(URLRequest(url: url)) }
    func loadPage(address urlString: String) {
        guard let url = URL(string: urlString) else { return }
        loadPage(address: url)
    }
}
28
Vasily Bodnarchuk

Avec Xcode 8, cela est maintenant possible, mais le moyen de le réaliser est un peu hacky pour le moins. Mais bon, une solution de travail est une solution de travail, non? Laissez-moi expliquer.

Le initWithCoder de WKWebView: n'est plus annoté comme "NS_UNAVAILABLE". Il semble maintenant comme indiqué ci-dessous.

- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

Commencez par sous-classer WKWebView et remplacez initWithCoder. Au lieu d'appeler super initWithCoder, vous devez utiliser une méthode d'initialisation différente, telle que initWithFrame: configuration :. Exemple rapide ci-dessous.

- (instancetype)initWithCoder:(NSCoder *)coder
{
    // An initial frame for initialization must be set, but it will be overridden 
    // below by the autolayout constraints set in interface builder. 
    CGRect frame = [[UIScreen mainScreen] bounds];
    WKWebViewConfiguration *myConfiguration = [WKWebViewConfiguration new];

    // Set any configuration parameters here, e.g.
    // myConfiguration.dataDetectorTypes = WKDataDetectorTypeAll; 

    self = [super initWithFrame:frame configuration:myConfiguration];

    // Apply constraints from interface builder.
    self.translatesAutoresizingMaskIntoConstraints = NO;

    return self;
}

Dans votre Storyboard, utilisez un UIView et donnez-lui une classe personnalisée de votre nouvelle sous-classe. Le reste fonctionne comme d'habitude (définition de contraintes de mise en page automatique, liaison de la vue à une prise d'un contrôleur, etc.).

Enfin, WKWebView adapte le contenu différemment à UIWebView. Beaucoup de gens vont probablement vouloir suivre le conseil simple décrit dans Supprimer WKWebView de la redimensionnement du contenu pour le rendre au même grossissement que le fait UIWebView pour que WKWebView suive de plus près le comportement de UIWebView à cet égard.

19
crx_au

Voici une version simple Swift 3 basée sur l'excellente réponse de crx_a.

import WebKit

class WKWebView_IBWrapper: WKWebView {
    required convenience init?(coder: NSCoder) {
        let config = WKWebViewConfiguration()
        //config.suppressesIncrementalRendering = true //any custom config you want to add
        self.init(frame: .zero, configuration: config)
        self.translatesAutoresizingMaskIntoConstraints = false
    }
}

Créez un UIView dans Interface Builder, affectez vos contraintes et affectez-le WKWebView_IBWrapper en tant que classe personnalisée, comme suit:

Utilities -> Identity Inspector Tab[1]

17
Gamma

Ceci est apparemment corrigé dans Xcode 9b4. Les notes de publication indiquent que "WKWebView est disponible dans la bibliothèque d'objets iOS."

Je n'ai pas encore cherché à savoir s'il nécessite iOS 11 ou s'il est compatible avec les versions antérieures.

4
EricS

Si vous rencontrez toujours ce problème dans les versions récentes de Xcode, c'est-à-dire v9.2 +, importez simplement Webkit sur votre ViewController:

#import <WebKit/WebKit.h>
  1. Avant le correctif: enter image description here

  2. Après le correctif:

enter image description here

2
MrDEV

Vous pouvez instancier et configurer un WKWebView dans IB depuis Xcode 9, inutile de le faire dans le code. enter image description here

Notez toutefois que votre cible de déploiement doit être supérieure à iOS 10, sinon vous obtiendrez une erreur lors de la compilation.

enter image description here

1
atineoSE

J'ai lié WebKit, maintenant ça marche!

example

0
daybreak zhou

Dans la version 9.0.1 de XCode, WKWebView est disponible sur Interface Builder.

0
ManuelMB