Xcode 9 GM: el soporte de WKWebView NSCoding estaba roto en versiones anteriores

155

¿Alguien sabe cómo solucionar este error con Xcode 9 GM? Estoy trabajando en una aplicación hecha con Xcode 8.3, el objetivo de implementación es para iOS 9.3 y nunca antes tuve este problema. Todavía no encuentro ninguna información aquí o en los foros de Apple :(

Editar: Este error se produjo cuando puse un WKWebView en el generador de interfaces, no si lo uso mediante programación.

Ver imagen WKWebView Error

Edición 2: Bueno, finalmente no es un error, consulte la respuesta de Quinn a continuación para obtener más información sobre este comportamiento. Gracias a él por la explicación.

Mehdi Chennoufi
fuente
1
Vea mi respuesta a continuación. Esto no es un error en Xcode 9; sin este error de compilación, en su lugar, se produciría un bloqueo en -initWithCoder: en tiempo de ejecución anterior a iOS 11.
Quinn Taylor
1
Solo cambio mi objetivo de implementación a 11
wei

Respuestas:

160

El error es el comportamiento correcto, y no un error en Xcode 9. Aunque WKWebView se introdujo en iOS 8, hubo un error -[WKWebView initWithCoder:]que solo se corrigió en iOS 11, que siempre fallaba en el tiempo de ejecución y, por lo tanto, impedía configurar uno dentro de Interface Builder.

https://bugs.webkit.org/show_bug.cgi?id=137160

En lugar de permitir a los desarrolladores construir algo en IB que se rompería en tiempo de ejecución, es un error de construcción. Es una limitación inconveniente ya que iOS 11 se lanzó recientemente, pero realmente no hay otra buena opción.

La solución para los objetivos de implementación anteriores es continuar agregando el WKWebView en el código, como @ fahad-ashraf ya describió en su respuesta:

https://developer.apple.com/documentation/webkit/wkwebview

Quinn Taylor
fuente
3
Hola Quinn, creo que el hombre que trabaja en Apple :-) También encontré su informe de error al respecto: lists.webkit.org/pipermail/webkit-unassigned/2014-September/... Gracias por su respuesta, es realmente sorprendente para los nuevos A los desarrolladores les gusto cuando nos encontramos con un comportamiento como ese. Gracias de nuevo.
Mehdi Chennoufi
¡Gracias! Fue útil.
ssowri1
2
¿Qué pasa si queremos apoyar en iOS10 también? en mi aplicación también necesito soporte para iOS 10 ¿Cómo podemos resolver este problema?
Kalikanth040494
¿Es curioso por qué Apple tardó hasta iOS 11 en encontrar una solución?
Eman
96

Esto parece ser un error en Xcode 9 y también estaba presente en las versiones beta. Solo obtendrá el error de compilación si está creando un WKWebView a través del guión gráfico. Si crea progmáticamente WKWebView en el archivo de clase ViewController correspondiente, debería poder construir en versiones de iOS inferiores a iOS 11. Este es el enfoque dado en el sitio web de Apple sobre cómo lograr esto:

import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {

    var webView: WKWebView!

    override func loadView() {
        super.loadView()
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }
    override func viewDidLoad() {
        super.viewDidLoad()

        let myURL = URL(string: "https://www.apple.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }}

Entonces debería poder implementar la funcionalidad WKWebView como lo haría normalmente.

Fuente: https://developer.apple.com/documentation/webkit/wkwebview

Fahad Ashraf
fuente
55
no lo olvidessuper.loadView()
albirrojo7
super.loadView()tiene que estar al principio. Sin eso, nada se muestra.
Makalele
hola :), ¿sabes cómo puedo establecer las restricciones de esto webviewdebajo de mi barra de navegación? Esta solución tuya funciona pero cubre toda la pantalla.
Abed Naseri
@AbedNaseri, creo que no es necesario poner restricciones ... puede crear una instancia del guión gráfico y luego self.navigationController? .PushViewController (youVC, animado: verdadero).
xhinoda
58

Si desea realizar una costumbreUIViewController con otros componentes además, puede hacer un "contenedor" a través del guión gráfico llamado, por ejemplo webViewContainer:

import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
    @IBOutlet weak var webViewContainer: UIView!
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let webConfiguration = WKWebViewConfiguration()
        let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.webViewContainer.frame.size.height))
        self.webView = WKWebView (frame: customFrame , configuration: webConfiguration)
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.webViewContainer.addSubview(webView)
        webView.topAnchor.constraint(equalTo: webViewContainer.topAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: webViewContainer.rightAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: webViewContainer.leftAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: webViewContainer.bottomAnchor).isActive = true
        webView.heightAnchor.constraint(equalTo: webViewContainer.heightAnchor).isActive = true
        webView.uiDelegate = self

        let myURL = URL(string: "https://www.apple.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }
Alessandro Ornano
fuente
Muchas gracias, realmente es de ayuda. Es un error conocido por Apple
Sébastien REMY
1
¡Trabajó! probado en iOS 11 y swift 4.1
Alwin
2
Si recibe el error [LayoutConstraints] Unable to simultaneously satisfy constraints, no olvide la línea webView.translatesAutoresizingMaskIntoConstraints = false. Si lo deja establecido en verdadero, creará un conjunto completo de restricciones para usted webViewautomáticamente, lo que entrará en conflicto con las restricciones que agregue mediante programación. Apple Docs .
mogelbuster
51

Si se trasladó de un objetivo anterior a iOS 11.0 y todavía recibe este error, utilice la solución a continuación.

  1. Vaya a Storyboard (Main.storyboard), haga clic en cualquier escena.
  2. Seleccione 'Inspector de archivos', que es la ventana de propiedades del lado derecho de Xcode
  3. Cambie el valor ' Compilaciones para ' a ' iOS 11.0 y posterior '
  4. Compilar y construir

ingrese la descripción de la imagen aquí

Kampai
fuente
2
@VyachaslavGerchicov: No sé sobre usted, pero en la industria, tenemos proyectos tan antiguos que deben convertirse a tecnología más nueva. Tantos que enfrentan el mismo problema. Ya mencioné en la respuesta que "si te mueves del objetivo anterior". No pienses en un solo caso.
Kampai el
1
Esto funciona para mí, gracias por señalar esta molesta configuración de IB. La advertencia se fue de inmediato. En realidad, creo que esta respuesta es más práctica y debería aceptarse. De acuerdo con @Kampai, en realidad, nos vemos obligados a pasar a la nueva versión de iOS, ya que Apple sigue cambiando sus marcos fundamentales
infinity_coding7
Después de hacerlo cuando se ejecuta en el simulador con la aplicación iOS 10.x se bloquea.
Ramis
@Ramis: Lo estaba haciendo para iOS 10, nunca tuve un bloqueo de la aplicación, ¿cuál era el registro de bloqueo?
Kampai
1
La solución más simple para solucionar este problema. ¡Gracias!
Jerry Chong
18

Me he enfrentado al mismo problema, pero puede abordarse si agregamos WKWebView mediante programación.

  1. Haga el diseño que desee hacer en el guión gráfico, pero deje espacio para WKWebView , en esa área arrastre y suelte una vista y asígnele el nombre webViewContainer y declare estas dos propiedades,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
  2. Ahora cree y agregue webView así:

    -(instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        self.webView = [self createWebView];
        self = [super initWithCoder:aDecoder];
        return self;
    }

    La función createWebView se declara como,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
  3. Ahora agregue este webView recién creado a su containerView, así:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
  4. Finalmente, simplemente cargue su URL de esta manera,

    -(void)webViewLoadUrl:(NSString *)stringUrl
    {
         NSURL *url = [NSURL URLWithString:stringUrl];
         NSURLRequest *request = [NSURLRequest requestWithURL:url];
         [self.webView loadRequest:request];
    }

Gracias por leer esto.

Najam
fuente
3

WebKit se introdujo en iOS 8 pero se lanzó con un error que provocó un bloqueo en tiempo de ejecución. Si está utilizando Xcode 9/10 , la configuración de su proyecto es compatible con menos de iOS 11 y si está tratando de agregar WKWebView utilizando el generador de interfaces. Xcode muestra inmediatamente un error en tiempo de compilación.

WKWebView antes de iOS 11.0 (NSCoding Support estaba roto en la versión anterior)

Aunque WKWebView se introdujo en iOS 8 , hubo un error en - [WKWebView initWithCoder:] que solo se solucionó en iOS 11 .

ingrese la descripción de la imagen aquí

La resolución es que debe agregar WKWebView a través del código (solo si es compatible con iOS 11). Eso en realidad suena extraño.

Otra solución es cambiar las compilaciones de documentos de Interface Builder para la opción a iOS 11 y posterior (si está migrando desde un destino anterior a iOS 11 y sigue obteniendo el mismo error).

Sr. Javed Multani
fuente
1

// Para Swift

import WebKit

class ViewController: UIViewController {
var webView: WKWebView!

// MARK:- WebView Configure
override func loadView() {
    let webConfig = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfig)
    view = webView
}


override func viewDidLoad() {
    super.viewDidLoad()
    // call urlrequest fun
    loadURLRequest()
}

//MARK:- Webview URLRequest
func loadURLRequest()  {
    let urlString = "https://www.google.com"
    let url = URL(string: urlString)
    let urlRequest = URLRequest(url: url!)
    webView.load(urlRequest)
}
}

// Para el objetivo C

#import <WebKit/WebKit.h>

@interface ViewController ()<WKNavigationDelegate,WKUIDelegate>{
WKWebView *webView;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
    
NSURL *url = [[NSURL alloc] initWithString: @"https://www.google.com"];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
    [webView loadRequest: request];
}


- (void)loadView {
[super loadView];

WKWebViewConfiguration *configu = [[WKWebViewConfiguration alloc] init];
webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configu];
webView.UIDelegate = self;
self.view = webView;
}

@end

ingrese la descripción de la imagen aquí

ShigaSuresh
fuente
0

Esto debería ser un comentario sobre la respuesta de Kampai, pero no tengo suficientes puntos de reputación para comentar.

Además de las versiones explícitas de iOS, el menú desplegable 'Compilaciones para' en el 'Inspector de archivos' también contiene la opción Destino de implementación (..) . Prefiero administrar versiones en un solo lugar si es posible y de todos modos quería cambiar el objetivo de compilación. Estaba completamente confundido, todavía decía Destino de implementación (9.3) aunque cambié la entrada correspondiente en la configuración general a 11.0 .

El reinicio de XCode (11.3.1) fue necesario para que todo funcionara como se esperaba, la opción 'Destino de implementación (11.0)' estaba disponible (y 9.3 desapareció). Después de la selección, todo funcionó como se esperaba.

ThomasB
fuente
0
import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    
    @IBOutlet weak var webViewContainer: UIView!
    private var webView: WKWebView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        addWebView()
        
        let myURL = URL(string: "https://www.apple.com")
        if let myURL = myURL {
            let myRequest = URLRequest(url: myURL)
            webView?.load(myRequest)
        }
    }
    
    private func addWebView() {
        let webConfiguration = WKWebViewConfiguration()
        let size = CGSize.init(width: 0.0, height: self.webViewContainer.frame.size.height)
        let customFrame = CGRect.init(origin: CGPoint.zero, size: size)
        self.webView = WKWebView (frame: customFrame, configuration: webConfiguration)
        if let webView = self.webView {
            webView.translatesAutoresizingMaskIntoConstraints = false
            self.webViewContainer.addSubview(webView)
            webView.topAnchor.constraint(equalTo: webViewContainer.topAnchor).isActive = true
            webView.rightAnchor.constraint(equalTo: webViewContainer.rightAnchor).isActive = true
            webView.leftAnchor.constraint(equalTo: webViewContainer.leftAnchor).isActive = true
            webView.bottomAnchor.constraint(equalTo: webViewContainer.bottomAnchor).isActive = true
            webView.heightAnchor.constraint(equalTo: webViewContainer.heightAnchor).isActive = true
            webView.uiDelegate = self
        }
    }
}
Deviyani Swami
fuente
-5

UIWebView está en desuso en iOS11 y WKWebView funciona solo en iOS11; esto suena como un error en Xcode GM.

pawel221
fuente
Sí. La única solución que encontré si desea implementar en una versión anterior de iOS es agregar su WKWebView mediante programación.
Mehdi Chennoufi