Xcode 9 GM - Obsługa WKWebView NSCoding została zerwana w poprzednich wersjach


155

Czy ktoś wie, jak naprawić ten błąd za pomocą Xcode 9 GM? Pracuję nad aplikacją stworzoną w Xcode 8.3, celem wdrożenia jest iOS 9.3 i nigdy wcześniej nie miałem tego problemu. Nie znalazłem jeszcze żadnych informacji tutaj ani na forach Apple :(

Edycja: ten błąd pojawił się, gdy umieściłem WKWebView w konstruktorze interfejsu, a nie, jeśli używam go programowo.

Zobacz zdjęcie Błąd WKWebView

Edycja 2: Cóż, w końcu to nie jest błąd, zobacz odpowiedź Quinna poniżej, aby uzyskać więcej informacji na temat tego zachowania. Dziękuję mu za wyjaśnienie.


1
Zobacz moją odpowiedź poniżej. To nie jest błąd w Xcode 9; bez tego błędu kompilacji zamiast tego wystąpiłaby awaria w -initWithCoder: w czasie wykonywania przed iOS 11.
Quinn Taylor

1
Po prostu zmieniam cel wdrożenia na 11
wei

Odpowiedzi:


160

Błąd jest prawidłowym zachowaniem, a nie błędem w Xcode 9. Chociaż WKWebView został wprowadzony w iOS 8, był błąd, -[WKWebView initWithCoder:]który został naprawiony tylko w iOS 11, który zawsze zawieszał się w czasie wykonywania, a tym samym uniemożliwiał skonfigurowanie go w Interface Builder.

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

Zamiast pozwalać programistom na budowanie czegoś w IB, co byłoby zepsute w czasie wykonywania, jest to błąd kompilacji. Jest to niewygodne ograniczenie, ponieważ iOS 11 został niedawno wydany, ale tak naprawdę nie ma innej dobrej opcji.

Obejściem problemu dla starszych celów wdrożenia jest kontynuowanie dodawania WKWebView w kodzie, jak @ fahad-ashraf już opisał w swojej odpowiedzi:

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


3
Cześć Quinn, wydaje mi się, że człowiek, który pracuje w Apple :-) Znalazłem również raport o błędzie na ten temat: lists.webkit.org/pipermail/webkit-unassigned/2014-Września/ ... Dziękuję za odpowiedź, to naprawdę zaskakujące dla nowych deweloperzy tacy jak ja, kiedy napotykamy takie zachowanie. Dzięki jeszcze raz.
Mehdi Chennoufi

Dziękuję Ci! To było przydatne.
ssowri1

2
co jeśli chcemy wspierać również w ios10? w mojej aplikacji muszę również obsługiwać iOS 10 Jak możemy rozwiązać ten problem?
Kalikanth040494

tylko ciekawy, dlaczego zajęło Apple aż iOS 11, aby znaleźć rozwiązanie?
Eman

96

Wygląda na to, że jest to błąd w Xcode 9 i był również obecny w wersjach beta. Błąd kompilacji zostanie wyświetlony tylko wtedy, gdy tworzysz WKWebView za pomocą scenorysu. Jeśli progmatycznie utworzysz WKWebView w odpowiednim pliku klasy ViewController, powinieneś być w stanie zbudować na wersjach iOS poniżej iOS 11. Oto podejście podane w witrynie Apple, aby to osiągnąć:

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

Powinieneś być wtedy w stanie zaimplementować funkcjonalność WKWebView w normalny sposób.

Źródło: https://developer.apple.com/documentation/webkit/wkwebview


5
nie zapomnijsuper.loadView()
albirrojo7

super.loadView()musi być na początku. Bez tego nic się nie pokazuje.
Makalele

cześć :), czy wiesz, jak mogę ustawić ograniczenia tego webviewponiżej mojego paska nawigacji? To rozwiązanie działa, ale obejmuje cały ekran.
Abed Naseri

@AbedNaseri Myślę, że nie musisz nakładać ograniczeń ... możesz utworzyć instancję storyboard, a następnie self.navigationController? .PushViewController (youVC, animated: true).
xhinoda,

58

Jeśli chcesz zrealizować zamówienieUIViewController z innymi komponentami dodatkowo, możesz utworzyć „kontener” poprzez scenorys o nazwie na przykład 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)
    }

Dziękuję bardzo, to naprawdę pomoc. To błąd znany przez Apple
Sébastien REMY

1
Pracowałem! testowany w iOS 11 i swift 4.1
Alwin

2
Jeśli otrzymujesz błąd [LayoutConstraints] Unable to simultaneously satisfy constraints, nie zapomnij o linii webView.translatesAutoresizingMaskIntoConstraints = false. Jeśli pozostawisz to ustawione na true, automatycznie utworzy cały zestaw ograniczeń, webViewktóre będą kolidować z ograniczeniami, które dodasz programowo. Apple Docs .
mogelbuster

51

Jeśli przeniesiesz się ze starszego celu do iOS 11.0 i nadal otrzymujesz ten błąd, użyj poniższego rozwiązania.

  1. Przejdź do Storyboard (Main.storyboard), kliknij dowolną scenę.
  2. Wybierz „Inspektor plików”, który jest prawym oknem właściwości Xcode
  3. Zmień wartość „ Builds for ” na „ iOS 11.0 and later
  4. Kompiluj i buduj

wprowadź opis obrazu tutaj


2
@VyachaslavGerchicov: Nie wiem jak wy, ale w branży mamy takie starsze projekty, które trzeba przestawić na nowsze technologie. Tak wielu ma ten sam problem. Wspomniałem już w odpowiedzi, że „jeśli zostaniesz przeniesiony ze starszego celu”. Nie myśl tylko o jednym przypadku.
Kampai

1
To działa dla mnie, dzięki za wskazanie tej irytującej konfiguracji IB. Ostrzeżenie znika od razu. Właściwie uważam, że ta odpowiedź jest bardziej praktyczna i powinna zostać zaakceptowana. Zgadzam się z @Kampai, właściwie jesteśmy zmuszeni przejść na nową wersję iOS, ponieważ Apple ciągle zmienia swoje podstawowe frameworki
infinity_coding7

Po zrobieniu tego podczas uruchamiania na symulatorze z aplikacją iOS 10.x ulega awarii.
Ramis

@Ramis: Robiłem to na iOS 10, nigdy nie miałem awarii aplikacji, jaki był dziennik awarii?
Kampai

1
Najprostsze rozwiązanie tego problemu. Dzięki!
Jerry Chong

18

Napotkałem ten sam problem, ale można go rozwiązać, dodając programowo WKWebView .

  1. Zrób dowolny projekt, który chcesz wykonać w scenorysie, ale zostaw miejsce na WKWebView , w tym obszarze przeciągnij i upuść widok i nazwij go jako webViewContainer i zadeklaruj te dwie właściwości,

    @property (weak, nonatomic) IBOutlet UIView *webViewContainer;
    @property(nonatomic, strong)WKWebView *webView;
  2. Teraz utwórz i dodaj webView w ten sposób:

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

    funkcja createWebView jest zadeklarowana jako,

    -(WKWebView *)createWebView
    {
         WKWebViewConfiguration *configuration = 
                   [[WKWebViewConfiguration alloc] init];
         return [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    }
  3. Teraz dodaj ten nowo utworzony widok webView do swojego containerView, na przykład:

    -(void)addWebView:(UIView *)view
    {
          [view addSubview:self.webView];
          [self.webView setTranslatesAutoresizingMaskIntoConstraints:false];
          self.webView.frame = view.frame;
    }
  4. Na koniec po prostu załaduj swój adres URL w ten sposób,

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

Dzięki za przeczytanie tego.


3

WebKit został wprowadzony w iOS 8, ale został wydany z błędem, który spowodował awarię środowiska uruchomieniowego, jeśli używasz Xcode 9/10 , konfiguracja twojego projektu obsługuje mniej niż iOS 11 i jeśli próbujesz dodać WKWebView za pomocą kreatora interfejsu. Xcode natychmiast pokazuje błąd w czasie kompilacji.

WKWebView przed iOS 11.0 (obsługa NSCoding była zepsuta w poprzedniej wersji)

Chociaż WKWebView został wprowadzony w iOS 8 , wystąpił błąd w - [WKWebView initWithCoder:], który został naprawiony tylko w iOS 11 .

wprowadź opis obrazu tutaj

Rozwiązanie polega na tym, że musisz dodać WKWebView za pomocą kodu (tylko jeśli obsługujesz poniżej iOS 11). To faktycznie brzmi dziwnie.

Innym rozwiązaniem jest zmiana kompilacji dokumentów Interface Builder dla opcji na system iOS 11 lub nowszy (jeśli migrujesz ze starszego celu do systemu iOS 11 i nadal występuje ten sam błąd).


1

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

// Dla celu 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

wprowadź opis obrazu tutaj


0

To powinien być komentarz do odpowiedzi Kampai, ale nie mam wystarczającej liczby punktów reputacji, aby to skomentować.

Oprócz jawnych wersji systemu iOS menu rozwijane „Kompilacje dla” w „Inspektorze plików” zawiera również opcję Cel wdrożenia (..) . Jeśli to możliwe, wolę zarządzać wersjami w jednym miejscu i mimo wszystko chciałem zmienić cel kompilacji. Byłem całkowicie zdezorientowany, ale nadal wskazywał cel wdrożenia (9.3), chociaż zmieniłem odpowiedni wpis w ustawieniach ogólnych na 11.0 .

Ponowne uruchomienie XCode (11.3.1) było konieczne, aby wszystko działało zgodnie z oczekiwaniami, dostępna była opcja „Cel wdrożenia (11.0)” (a 9.3 zniknął). Po dokonaniu selekcji wszystko działało zgodnie z oczekiwaniami.


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

-5

UIWebView jest przestarzałe w iOS11, a WKWebView działa tylko w iOS11 - to brzmi jak błąd w Xcode GM.


Tak. Jedynym obejściem, które znalazłem, jeśli chcesz wdrożyć w poprzedniej wersji iOS, jest programowe dodanie WKWebView.
Mehdi Chennoufi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.