undeclared type support previous example broken before ios xcode macos uiwebview wkwebview

ios - type - wkwebview example



WKWebView en Interface Builder (10)

Parece que las plantillas de objetos IB en XCode 6 beta todavía están creando objetos de estilo antiguo (UIWebView para iOS y WebView para OSX). Esperemos que Apple los actualice para el WebKit moderno, pero hasta entonces, ¿cuál es la mejor manera de crear WKWebViews en Interface Builder? ¿Debo crear una vista básica (UIView o NSView) y asignar su tipo a WKWebView? La mayoría de los ejemplos que encuentro en línea lo agregan a una vista de contenedor mediante programación; ¿Es eso mejor por alguna razón?


Xcode 9.1

Puede encontrar el elemento WKWebView en la biblioteca de objetos.

Swift 3 y Xcode 8

usando 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="_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="_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>

programáticamente

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


Aquí hay una versión simple de Swift 3 basada en la excelente respuesta de crx_au .

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

Cree un UIView en Interface Builder, asigne sus restricciones y asígnele WKWebView_IBWrapper como una clase personalizada, como esta:


Como señalaron algunos, a partir de Xcode 6.4, WKWebView todavía no está disponible en Interface Builder. Sin embargo, es muy fácil agregarlos a través del código.

Solo estoy usando esto en mi ViewController. Saltar constructor de interfaz

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


Con Xcode 8 esto ahora es posible, pero los medios para lograrlo son un poco hacky por decir lo menos. Pero bueno, una solución de trabajo es una solución de trabajo, ¿verdad? Dejame explicar.

WKWebView''s initWithCoder: ya no está anotado como "NS_UNAVAILABLE". Ahora se ve como se muestra a continuación.

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

Comience subclasando WKWebView y anule initWithCoder. En lugar de llamar a super initWithCoder, necesitará usar un método init diferente, como initWithFrame: configuration :. Ejemplo rápido a continuación.

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

En su Storyboard, use un UIView y dele una clase personalizada de su nueva subclase. El resto es lo de siempre (establecer restricciones de diseño automático, vincular la vista a una toma de corriente en un controlador, etc.).

Finalmente, WKWebView escala el contenido de manera diferente a UIWebView. Es probable que muchas personas deseen seguir los consejos simples de Suprimir WKWebView para escalar el contenido y procesarlo con el mismo aumento que UIWebView para hacer que WKWebView siga más de cerca el comportamiento de UIWebView a este respecto.


En XCode Versión 9.0.1 WKWebView está disponible en Interface Builder.


Esto ahora está aparentemente arreglado en Xcode 9b4. Las notas de la versión dicen "WKWebView está disponible en la biblioteca de objetos de iOS".

No he buscado más profundamente para ver si requiere iOS 11 o si aún es compatible con versiones anteriores.


Esto funcionó para mí en Xcode 7.2 ...

Primero agregue la vista web como una salida de UIWebView en el guión gráfico / IB. Esto le dará una propiedad como esta:

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

Luego edite su código para cambiarlo a WKWebView.

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

También debe cambiar la clase personalizada a WKWebView en el inspector de identidad.


Puede crear instancias y configurar un WKWebView en IB desde Xcode 9, sin necesidad de hacerlo en el código.

Tenga en cuenta que su destino de despliegue tiene que ser más alto que iOS 10 o tendrá un error en tiempo de compilación.


Si todavía enfrenta este problema en versiones recientes de Xcode, es decir, v9.2 +, simplemente importe Webkit ViewController:

#import <WebKit/WebKit.h>

  1. Antes de la corrección:

  2. Después de la corrección:


Tienes razón, parece que no funciona. Si miras en los encabezados, verás:

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

lo que implica que no puedes crear una instancia de una semilla.

Tendrás que hacerlo a mano en viewDidLoad o loadView.