Xcode 9 GM - WKWebView NSCoding-Unterstützung wurde in früheren Versionen unterbrochen

160

Weiß jemand, wie man diesen Fehler mit Xcode 9 GM behebt? Ich arbeite an einer App, die mit Xcode 8.3 erstellt wurde. Das Bereitstellungsziel ist iOS 9.3, und ich hatte dieses Problem noch nie zuvor. Ich finde hier oder in Apple-Foren noch keine Informationen :(

Bearbeiten: Dieser Fehler trat auf, wenn ich ein WKWebView in den Interface Builder einfügte, nicht wenn ich es programmgesteuert verwende.

Siehe Bild WKWebView-Fehler

Edit 2: Nun, es ist endlich kein Fehler. Weitere Informationen zu diesem Verhalten finden Sie in Quinns Antwort unten. Danke an ihn für die Erklärung.

Mehdi Chennoufi
quelle
1
Siehe meine Antwort unten. Dies ist kein Fehler in Xcode 9; Ohne diesen Build-Fehler würden Sie stattdessen einen Absturz in -initWithCoder erhalten: zur Laufzeit vor iOS 11.
Quinn Taylor
1
Ich ändere gerade mein Bereitstellungsziel auf 11
wei
Dies sollte ein Kommentar zu Kampais Antwort sein, aber ich habe nicht genug Reputationspunkte, um einen Kommentar abzugeben. Neben expliziten iOS-Versionen enthält die Dropdown-Liste "Builds für" im "File Inspector" auch die Option " Deployment Target (..) ". Ich bevorzuge es, wenn möglich, Versionen an einem einzigen Ort zu verwalten und wollte das Build-Ziel trotzdem ändern. Ich war völlig verwirrt, dass immer noch Deployment Target (9.3) angezeigt wurde, obwohl ich den entsprechenden Eintrag in den allgemeinen Einstellungen in 11.0 geändert habe . Ein Neustart von XCode (11.3.1) war erforderlich, damit alles wie erwartet funktioniert. Die Option 'Bereitstellungsziel (11.0)' war
ThomasB

Antworten:

163

Der Fehler ist korrektes Verhalten und kein Fehler in Xcode 9. Obwohl WKWebView in iOS 8 eingeführt wurde, gab es einen Fehler -[WKWebView initWithCoder:], der nur in iOS 11 behoben wurde, der immer zur Laufzeit abstürzte und somit die Konfiguration eines solchen in Interface Builder verhinderte.

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

Anstatt Entwicklern zu erlauben, etwas in IB zu erstellen, das zur Laufzeit fehlerhaft wäre, handelt es sich um einen Erstellungsfehler. Dies ist eine unpraktische Einschränkung, da iOS 11 erst kürzlich veröffentlicht wurde, aber es gibt wirklich keine andere gute Option.

Die Problemumgehung für ältere Bereitstellungsziele besteht darin, das WKWebView weiterhin im Code hinzuzufügen, wie @ fahad-ashraf bereits in seiner Antwort beschrieben hat:

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

Quinn Taylor
quelle
3
Hallo Quinn, ich glaube dem Mann, der bei Apple arbeitet :-) Ich habe auch Ihren Fehlerbericht darüber gefunden: lists.webkit.org/pipermail/webkit-unassigned/2014-September/… Vielen Dank für Ihre Antwort, es ist wirklich überraschend für neue Entwickler wie ich, wenn wir auf ein solches Verhalten stoßen. Danke noch einmal.
Mehdi Chennoufi
Vielen Dank! Es war nützlich.
ssowri1
2
Was ist, wenn wir auch in ios10 unterstützen wollen? In meiner App muss ich auch iOS 10 unterstützen. Wie können wir dieses Problem lösen?
Kalikanth040494
Nur neugierig, warum Apple bis iOS 11 gebraucht hat, um eine Lösung zu finden.
Eman
97

Dies scheint ein Fehler in Xcode 9 zu sein und war auch in den Betas vorhanden. Der Build-Fehler wird nur angezeigt, wenn Sie eine WKWebView über das Storyboard erstellen. Wenn Sie die WKWebView progmatisch in der entsprechenden ViewController-Klassendatei erstellen, sollten Sie in der Lage sein, auf iOS-Versionen unter iOS 11 aufzubauen. Hier ist der auf der Apple-Website angegebene Ansatz, um dies zu erreichen:

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

Sie sollten dann in der Lage sein, die WKWebView-Funktionalität wie gewohnt zu implementieren.

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

Fahad Ashraf
quelle
5
nicht vergessensuper.loadView()
albirrojo7
super.loadView()muss am Anfang sein. Ohne es zeigt sich nichts.
Makalele
Hallo :), weißt du, wie ich die Einschränkungen webviewunter meiner Navigationsleiste festlegen kann ? Diese Lösung von Ihnen funktioniert, deckt aber den gesamten Bildschirm ab.
Abed Naseri
@AbedNaseri Ich denke, Sie müssen keine Einschränkungen festlegen ... Sie können das Storyboard und dann den self.navigationController instanziieren? .PushViewController (youVC, animiert: true).
Xhinoda
59

Wenn Sie zusätzlich eine benutzerdefinierte FunktionUIViewController mit anderen Komponenten realisieren möchten, können Sie über das Storyboard einen "Container" erstellen, der beispielsweise Folgendes enthält 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: self.webViewContainer.frame.size.width, 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
quelle
Vielen Dank, es ist wirklich hilfreich. Es ist ein Fehler, den Apple kennt
Sébastien REMY
1
Hat funktioniert! getestet in iOS 11 und schnell 4.1
Alwin
2
Wenn Sie den Fehler erhalten [LayoutConstraints] Unable to simultaneously satisfy constraints, vergessen Sie die Zeile nicht webView.translatesAutoresizingMaskIntoConstraints = false. Wenn Sie den Wert auf true setzen, werden webViewautomatisch eine Reihe von Einschränkungen für Sie erstellt , die mit den programmgesteuert hinzugefügten Einschränkungen in Konflikt stehen. Apple Docs .
Mogelbuster
1
Ändern Sie einfach die folgende Zeile Von: let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.webViewContainer.frame.size.height)) Bis: let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: self.webViewContainer.frame.size.width, height: self.webViewContainer.frame.size.height))
Syed Faizan Ahmed
56

Wenn Sie von einem älteren Ziel auf iOS 11.0 verschoben wurden und dennoch dieser Fehler angezeigt wird, verwenden Sie die folgende Lösung.

  1. Gehen Sie zum Storyboard (Main.storyboard) und klicken Sie auf eine beliebige Szene.
  2. Wählen Sie 'Dateiinspektor', das ist das rechte Eigenschaftsfenster von Xcode
  3. Ändern Sie den Wert für " Builds for " in " iOS 11.0 und höher ".
  4. Kompilieren und erstellen

Geben Sie hier die Bildbeschreibung ein

Kampai
quelle
2
@VyachaslavGerchicov: Ich weiß nichts über Sie, aber in der Branche haben wir solche älteren Projekte, die auf neuere Technologien umgestellt werden müssen. So viele stehen vor dem gleichen Problem. Ich habe bereits in der Antwort erwähnt, dass "wenn Sie von einem älteren Ziel bewegt werden". Denken Sie nicht nur an einen Fall.
Kampai
1
Das funktioniert bei mir, danke, dass Sie auf dieses nervige IB-Setup hingewiesen haben. Die Warnung ist sofort weg. Eigentlich halte ich das für praktischer und sollte als Antwort akzeptiert werden. Stimmen Sie mit @Kampai überein, tatsächlich sind wir gezwungen, auf die neue Version von iOS umzusteigen, da Apple seine grundlegenden Frameworks ständig ändert
infinity_coding7
Danach stürzt die App ab, wenn sie auf einem Simulator mit iOS 10.x ausgeführt wird.
Ramis
@ Ramis: Ich habe es für iOS 10 gemacht, ich habe nie einen App-Absturz bekommen. Was war das Absturzprotokoll?
Kampai
1
Einfachste Lösung zur Behebung dieses Problems. Vielen Dank!
Jerry Chong
18

Ich habe das gleiche Problem, aber es kann angegangen werden, wenn wir WKWebView programmgesteuert hinzufügen .

  1. Führen Sie das gewünschte Design im Storyboard aus, verlassen Sie jedoch den Raum für WKWebView. Ziehen Sie in diesem Bereich eine Ansicht per Drag & Drop, benennen Sie sie als webViewContainer und deklarieren Sie diese beiden Eigenschaften.

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
    
  2. Erstellen und fügen Sie nun WebView wie folgt hinzu:

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

    Die Funktion createWebView wird wie folgt deklariert:

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
    
  3. Fügen Sie nun diese neu erstellte WebView wie folgt zu Ihrer containerView hinzu:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
    
  4. Zum Schluss laden Sie einfach Ihre URL so,

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

Danke, dass Sie dies gelesen haben.

Najam
quelle
3

WebKit wurde in iOS 8 eingeführt, aber mit einem Fehler veröffentlicht, der zu einem Laufzeitabsturz führte. Wenn Sie Xcode 9/10 verwenden , unterstützt Ihre Projektkonfiguration weniger als iOS 11 und wenn Sie versuchen, WKWebView mithilfe des Interface Builder hinzuzufügen. Xcode zeigt sofort einen Fehler bei der Kompilierung an.

WKWebView vor iOS 11.0 (NSCoding-Unterstützung wurde in der vorherigen Version unterbrochen)

Obwohl WKWebView in iOS 8 eingeführt wurde , gab es einen Fehler in - [WKWebView initWithCoder:], der nur in iOS 11 behoben wurde .

Geben Sie hier die Bildbeschreibung ein

Die Lösung ist, dass Sie WKWebView über Code hinzufügen müssen (nur wenn Sie unter iOS 11 unterstützen). Das klingt eigentlich komisch.

Eine andere Lösung besteht darin, die Interface Builder-Dokumenterstellungen für die Option auf iOS 11 und höher zu ändern (wenn Sie von einem älteren Ziel auf iOS 11 migrieren und immer noch den gleichen Fehler erhalten).

Mr.Javed Multani
quelle
2

// Für 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)
}
}

// Für Ziel 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

Geben Sie hier die Bildbeschreibung ein

ShigaSuresh
quelle
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
quelle
-5

UIWebView ist in iOS11 veraltet und WKWebView funktioniert nur in iOS11 - dies klingt nach einem Fehler in Xcode GM.

pawel221
quelle
Ja. Die einzige Problemumgehung, die ich gefunden habe, wenn Sie auf einer früheren Version von iOS bereitstellen möchten, ist das programmgesteuerte Hinzufügen Ihres WKWebView.
Mehdi Chennoufi