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?
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.
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)
}
}
}
Info.plist
ajoutez dans votre paramètre de sécurité de transport Info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Utilisation du constructeur d'interface
Vous pouvez trouver l'élément WKWebView dans la bibliothèque d'objets.
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)
}
}
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.
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:
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.
Dans la version 9.0.1 de XCode, WKWebView est disponible sur Interface Builder.