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?
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.
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)
}
}
}
Xcode 9.1
vous pouvez trouver l'élément WKWebView dans la bibliothèque D'objets.
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))
}
}
}
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.
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:
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.
vous pouvez instancier et configurer un WKWebView en IB depuis Xcode 9, Pas besoin de le faire en code.
notez que votre cible de déploiement doit être supérieure à iOS 10, sinon vous obtiendrez une erreur de compilation.
dans la Version 9.0.1 de XCode WKWebView est disponible sur Interface Builder.
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>
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é.