WKWebView in Interface Builder

il semble que les modèles D'objets IB de XCode 6 beta créent encore des objets anciens (UIWebView pour iOS et WebView pour OSX). Avec un peu de chance, Apple les mettra à jour pour le WebKit moderne, mais d'ici là, quelle est la meilleure façon de créer Wkwebviews dans Interface Builder? Dois-je créer une vue de base (UIView ou NSView) et attribuer son type à WKWebView? La plupart des exemples que j'ai trouver en ligne l'ajouter à un conteneur en vue par programme, est-ce mieux pour une raison quelconque?

87
demandé sur Steve Landey 2014-06-11 20:16:59

10 réponses

Vous avez raison - il 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'un nib.

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

67
répondu EricS 2014-06-19 03:37:37

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

j'utilise juste ceci dans mon ViewController. Skipping Interface builder

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
répondu Johan 2017-09-07 15:51:13

Xcode 9.1

vous pouvez trouver l'élément WKWebView dans la bibliothèque D'objets.

enter image description here

Swift 3 et Xcode 8

utilisant le StoryBoard

ViewController.swift

import UIKit
import WebKit

// Add WKWebView in StoryBoard
class ViewController: UIViewController {

    @IBOutlet var webView: WebView!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        webView.loadUrl(string: "http://apple.com")
    }
}

class WebView: WKWebView {

    required init?(coder: NSCoder) {

        if let _view = UIView(coder: coder) {
            super.init(frame: _view.frame, configuration: WKWebViewConfiguration())
            autoresizingMask = _view.autoresizingMask
        } else {
            return nil
        }
    }

    func loadUrl(string: String) {
        if let url = URL(string: string) {
            load(URLRequest(url: url))
        }
    }
}

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_24167812" customModuleProvider="target" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0zg-ri-o6Y" customClass="WebView" customModule="stackoverflow_24167812" customModuleProvider="target">
                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                            </view>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    </view>
                    <connections>
                        <outlet property="webView" destination="0zg-ri-o6Y" id="G0g-bh-eej"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="140" y="138.98050974512745"/>
        </scene>
    </scenes>
</document>

par programme

import UIKit
import WebKit

// Add WKWebView programmatically
class ViewController: UIViewController {

    var webView: WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()
        // init webView
        webView = WKWebView(frame: view.bounds)
        view.addSubview(webView!)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // load url
        webView?.loadUrl(string: "http://apple.com")
    }
}

extension WKWebView {
    func loadUrl(string: String) {
        if let url = URL(string: string) {
            load(URLRequest(url: url))
        }
    }
}
27
répondu Vasily Bodnarchuk 2018-04-14 09:28:29

avec Xcode 8 c'est maintenant possible, mais le moyen d'y parvenir est un peu hacky pour le moins. Mais une solution qui fonctionne, c'est une solution qui fonctionne, non? Laissez-moi vous expliquer.

initwwebview avec codeur: n'est plus annoté "NS_UNAV accessible". Il ressemble maintenant comme indiqué ci-dessous.

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

commence par sous-classer WKWebView et remplace initWithCoder. Au lieu d'appeler super initWithCoder, vous aurez besoin d'utiliser un init différent méthode, 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 uivi et donnez-lui une classe personnalisée de votre nouvelle sous-classe. Le reste est du business as usual (mise en place de contraintes d'Auto-layout, liaison de la vue à une sortie dans un contrôleur, etc).

enfin, WKWebView évalue le contenu différemment de UIWebView. Beaucoup de gens vont probablement vouloir suivre le simple conseil dans Supprimer WKWebView de mise à l'échelle le contenu de rendre au même grossissement que UIWebView ne pour faire WKWebView suivre de plus près les UIWebView comportement à cet égard.

18
répondu crx_au 2017-05-23 11:55:01

Voici une version simple de Swift 3 basée sur crx_au excellente réponse.

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, assignez vos contraintes, et assignez-le WKWebView_IBWrapper comme une classe personnalisée, comme ceci:

Utilities - Identity Inspector Tab[1]

11
répondu Gamma 2017-07-17 11:14:14

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

Je n'ai pas cherché plus en profondeur pour voir si elle Nécessite iOS 11 ou si elle est encore compatible avec l'arrière.

4
répondu EricS 2017-07-24 18:59:28

vous pouvez instancier et configurer un WKWebView en IB depuis Xcode 9, Pas besoin de le faire en code. enter image description here

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

enter image description here

1
répondu atineoSE 2018-05-03 14:42:48

dans la Version 9.0.1 de XCode WKWebView est disponible sur Interface Builder.

0
répondu ManuelMB 2017-10-26 14:38:58

si vous rencontrez toujours ce problème dans les versions récentes de Xcode, i.e. v9.2+, Il suffit d'importer Webkit pour vous ViewController:

#import <WebKit/WebKit.h>
  1. avant le point: enter image description here

  2. après le point fixe:

enter image description here

0
répondu MrDEV 2018-02-22 17:39:46

cela a fonctionné pour moi dans le Xcode 7.2...

tout d'abord ajouter la vue web comme une sortie UIWebView dans le storyboard / IB. Cela vous donnera une propriété comme ceci:

@property (weak, nonatomic) IBOutlet UIWebView *webView;

éditez votre code pour le changer en WKWebView.

@property (weak, nonatomic) IBOutlet WKWebView *webView;

vous devriez également changer la classe personnalisée à WKWebView dans l'Inspecteur D'identité.

-12
répondu Pat McG 2015-12-13 19:26:46