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.

Mehdi Chennoufi
źródło
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

Quinn Taylor
źródło
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

Fahad Ashraf
źródło
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)
    }
Alessandro Ornano
źródło
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

Kampai
źródło
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.

Najam
źródło
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).

Panie Javed Multani
źródło
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

ShigaSuresh
źródło
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.

ThomasB
źródło
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
źródło
-5

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

pawel221
źródło
Tak. Jedynym obejściem, które znalazłem, jeśli chcesz wdrożyć w poprzedniej wersji iOS, jest programowe dodanie WKWebView.
Mehdi Chennoufi