Xcode 9 GM - O suporte ao WSCWebView NSCoding foi quebrado nas versões anteriores

155

Alguém sabe como corrigir esse erro com o Xcode 9 GM? Estou trabalhando em um aplicativo criado com o Xcode 8.3, o destino de implantação é o iOS 9.3 e nunca tive esse problema antes. Ainda não encontro informações aqui ou nos fóruns da Apple :(

Edit: Este erro ocorreu quando eu coloquei um WKWebView no construtor de interfaces, não se eu o usar programaticamente.

Ver imagem WKWebView Error

Edit 2: Bem, finalmente não é um bug, veja a resposta de Quinn abaixo para obter mais informações sobre esse comportamento. Obrigado a ele pela explicação.

Mehdi Chennoufi
fonte
1
Veja minha resposta abaixo. Isso não é um bug no Xcode 9; sem este erro de compilação, você iria em vez de obter um acidente em -initWithCoder: em tempo de execução antes do iOS 11.
Quinn Taylor
1
Eu só mudar o meu destino de implementação para 11
wei

Respostas:

160

O erro é o comportamento correto, e não um bug no Xcode 9. Embora o WKWebView tenha sido introduzido no iOS 8, havia um bug -[WKWebView initWithCoder:]corrigido apenas no iOS 11, que sempre travava no tempo de execução e, portanto, impedia a configuração de um no Interface Builder.

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

Em vez de permitir que os desenvolvedores criem algo no IB que seria quebrado no tempo de execução, é um erro de compilação. É uma limitação inconveniente, já que o iOS 11 foi lançado recentemente, mas não há outra boa opção.

A solução alternativa para destinos de implantação mais antigos é continuar adicionando o WKWebView no código, como @ fahad-ashraf já descrito em sua resposta:

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

Quinn Taylor
fonte
3
Olá Quinn, acredito que o homem que trabalha na Apple :-) Também encontrei seu relatório de erro sobre isso: lists.webkit.org/pipermail/webkit-unassigned/2014-Setembro/… Obrigado por sua resposta, é realmente surpreendente para novos desenvolvedores como eu quando encontramos um comportamento como esse. Obrigado novamente.
Mehdi Chennoufi 10/10
Obrigado! Isso foi útil.
precisa saber é o seguinte
2
e se quisermos apoiar no ios10 também? No meu aplicativo, eu preciso oferecer suporte ao iOS 10 também. Como podemos resolver esse problema?
Kalikanth040494
apenas curioso, por que a Apple demorou até o iOS 11 para descobrir uma solução?
Eman
96

Isso parece ser um bug no Xcode 9 e também estava presente nos betas. Você só receberá o erro de construção se estiver criando um WKWebView através do storyboard. Se você criar progressivamente o WKWebView no arquivo de classe ViewController correspondente, poderá criar versões do iOS abaixo do iOS 11. Aqui está a abordagem fornecida no site da Apple para saber como fazer isso:

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

Você poderá implementar a funcionalidade WKWebView como faria normalmente.

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

Fahad Ashraf
fonte
5
Não se esqueça desuper.loadView()
albirrojo7
super.loadView()tem que estar no começo. Sem ele, nada mostra.
Makalele 27/03
oi :), você sabe como posso definir as restrições disso webviewabaixo da minha NavigationBar? Essa solução funciona, mas cobre a tela inteira.
Abed Naseri 4/06
@AbedNaseri eu acho que você não precisa colocar restrições ... você pode instanciar storyboard e depois self.navigationController? .PushViewController (youVC, animated: true).
xhinoda
58

Se você deseja realizar um costumeUIViewController com outros componentes, pode criar um "contêiner" através do storyboard chamado, por exemplo 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
fonte
Muito obrigado, é realmente ajuda. É um bug conhecido pela Apple
Sébastien REMY
1
Trabalhou! testado no iOS 11 e swift 4.1
Alwin
2
Se você está recebendo o erro [LayoutConstraints] Unable to simultaneously satisfy constraints, não esqueça a linha webView.translatesAutoresizingMaskIntoConstraints = false. Se você deixar definido como verdadeiro, ele criará um conjunto inteiro de restrições webViewautomaticamente, o que entrará em conflito com as restrições adicionadas programaticamente. Documentos da Apple .
Mogelbuster 15/1018
51

Se você passou do destino mais antigo para o iOS 11.0 e ainda está recebendo esse erro, use a solução abaixo.

  1. Vá para Storyboard (Main.storyboard), clique em qualquer Cena.
  2. Selecione 'File Inspector', que é a janela de propriedades do lado direito do Xcode
  3. Altere o valor " Constrói para " para " iOS 11.0 e posterior "
  4. Compilar e construir

insira a descrição da imagem aqui

Kampai
fonte
2
@VyachaslavGerchicov: Eu não sei sobre você, mas na indústria, temos projetos mais antigos que precisam ser convertidos em novas tecnologias. Muitos enfrentando o mesmo problema. Eu já mencionei na resposta que "se você for movido do alvo mais antigo". Não pense em apenas um caso.
Kampai
1
Isso funciona para mim, obrigado por apontar essa configuração irritante de IB. O aviso se foi imediatamente. Na verdade, acho isso mais prático e deve ser aceito como resposta. Concordo com @Kampai, na verdade, somos forçados a mover-se para a nova versão do iOS, já que o da Apple sempre a mudar suas estruturas fundamentais
infinity_coding7
Depois de fazer isso ao executar no simulador com o aplicativo iOS 10.x, ele falha.
Ramis
@Ramis: Eu estava fazendo isso no iOS 10, nunca tive falha no aplicativo, qual era o log de falha?
Kampai
1
Solução mais simples para corrigir esse problema. Obrigado!
21719 Jerry Chong
18

Eu enfrentei o mesmo problema, mas ele pode ser resolvido se adicionarmos o WKWebView programaticamente.

  1. Faça o design que você deseja criar no storyboard, mas deixe o espaço para o WKWebView ; nessa área, arraste e solte uma visualização e nomeie-a como webViewContainer e declare essas duas propriedades,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
  2. Agora crie e adicione o webView da seguinte maneira:

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

    A função createWebView é declarada como,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
  3. Agora adicione este webView recém-criado ao seu containerView, desta forma:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
  4. Por fim, basta carregar seu URL assim,

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

Obrigado por ler isso.

Najam
fonte
3

O WebKit foi introduzido no iOS 8, mas foi lançado com um erro que causava uma falha de tempo de execução. Se você estiver usando o Xcode 9/10 , a configuração do seu projeto suporta menos do que o iOS 11 e se você estiver tentando adicionar o WKWebView usando o construtor de interface. O Xcode mostra imediatamente um erro em tempo de compilação.

WKWebView antes do iOS 11.0 (o suporte a NSCoding foi quebrado na versão anterior)

Embora o WKWebView tenha sido introduzido no iOS 8 , houve um erro em - [WKWebView initWithCoder:] que foi corrigido apenas no iOS 11 .

insira a descrição da imagem aqui

A resolução é que você deve adicionar o WKWebView através do código (somente se você estiver suportando abaixo do iOS 11). Isso realmente soa estranho.

Outra solução é alterar as compilações de documentos do Interface Builder para a opção iOS 11 e posterior (se você estiver migrando do destino mais antigo para o iOS 11 e ainda obtendo o mesmo erro).

Mr.Javed Multani
fonte
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 o 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

insira a descrição da imagem aqui

ShigaSuresh
fonte
0

Deve ser um comentário à resposta de Kampai, mas não tenho pontos de reputação suficientes para comentar.

Além das versões explícitas do iOS, o menu suspenso 'Constrói para' no 'Inspetor de arquivos' também contém a opção Destino de implantação (..) . Prefiro gerenciar versões em um único local, se possível, e desejava alterar o destino da compilação de qualquer maneira. Fiquei totalmente confuso, pois ainda dizia Destino de Implantação (9.3), embora eu tenha alterado a entrada correspondente nas configurações gerais para 11.0 .

A reinicialização do XCode (11.3.1) era necessária para que tudo funcionasse conforme o esperado, a opção 'Destino de Implantação (11.0)' estava disponível (e 9.3 desapareceu). Após a seleção, tudo funcionou como esperado.

ThomasB
fonte
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
fonte
-5

O UIWebView foi descontinuado no iOS11 e o WKWebView funciona apenas no iOS11 - isso soa como um bug no Xcode GM.

pawel221
fonte
Sim. A única solução alternativa que encontrei se você deseja implantar na versão anterior do iOS é adicionar o WKWebView programaticamente.
Mehdi Chennoufi 15/09