WKWebView у конструкторі інтерфейсів


95

Здається, шаблони об’єктів IB у бета-версії XCode 6 все ще створюють об’єкти старого стилю (UIWebView для iOS та WebView для OSX). Сподіваємось, Apple оновить їх для сучасного WebKit, але до тих пір, який найкращий спосіб створити WKWebViews у Interface Builder? Чи слід створювати базовий вигляд (UIView або NSView) і призначати його тип WKWebView? Більшість прикладів, які я знаходжу в Інтернеті, програмно додають його до перегляду контейнера; чи це чомусь краще?


3
Це все ще відкрита помилка: lists.webkit.org/pipermail/webkit-unassigned/2014-September/…
— David H

4
Я використовую Xcode 7.2, я не бачу WKWebView у бібліотеці об’єктів. Він все ще недоступний?
— user3731622

10
Досі немає в Xcode 8.
— Райан Баллантайн

1
Xcode 9.0.1 тепер підтримує WKWebView в IB. Усі відповіді тут застаріли.
— посмішкаБот

1
@smileBot У новій версії Xcode дійсно є WKWebView, але вона вимагає націлювання на iOS 11+. crx_au відповідь працює краще -> stackoverflow.com/a/40118654/757503
— mikemike396

Відповіді:


70

Ви праві - це, здається, не працює. Якщо заглянути в заголовки, ви побачите:

- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;

це означає, що ви не можете створити екземпляр з перо.

Вам доведеться зробити це вручну у viewDidLoad або loadView.


Сподіваємось, вони в якийсь момент це змінять, але, гадаю, це не велика проблема. Йохан вказав мені назад на відео WWDC, і навіть вони створюють екземпляри в коді.
— Адам Фокс,

3
Позитивною стороною є те, що виконання цього в коді дозволить вам використовувати UIWebView в iOS 7 і WKWebView в iOS 8.
— EricS

Ну, після цієї відповіді, я думаю, ви можете замінити цей метод у підкласі WKWebView, а потім використовувати його в конструкторі інтерфейсів .. але без super.initWithCoder .. давайте перевіримо! :)
— zarghol

1
Після особистого тесту: ти не можеш ... "Неможливо замінити" init ", який був позначений як недоступний" дуже погано ...
— zarghol

2
Розумною справою може бути створення підпрогляду UIView під назвою MyWebView, який має або WKWebView, або UIWebView як підпогляд, визначений під час виконання в initWithCoder. Тоді ви можете створити подання MyWebView у IB. Якщо ви використовуєте Swift, ви навіть можете додати властивості, які можна редагувати в IB за допомогою ключового слова IBInspectable.
— EricS

65

Як зазначають деякі, станом на Xcode 6.4, WKWebView все ще недоступний у Interface Builder. Однак дуже легко додати їх за допомогою коду.

Я просто використовую це у своєму ViewController. Пропуск конструктора інтерфейсу

import UIKit
import WebKit

class ViewController: UIViewController {

    private var webView: WKWebView?

    override func loadView() {
        webView = WKWebView()

        //If you want to implement the delegate
        //webView?.navigationDelegate = self

        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if let url = URL(string: "https://google.com") {
            let req = URLRequest(url: url)
            webView?.load(req)
        }
    }
}

13
Це питання стосується Interface Builder, тому ця відповідь не надто корисна.
— Стів Ленді,

5
Ти правий. Я повинен був розпочати відповідь з "Ви не можете створити WKWebView з IB" :) Але я дивлюсь відео сеансу "Представляємо сучасний API WebKit" від WWDC, і вони використовують Xcode, тому я думаю, що це просто щось, що не ' t доступні нам на даний момент.
— Йохан

1
Щойно перевірили відео ще раз, і вони створюють екземпляр свого WKWebView у коді. Це близько позначки 17:20 у відео.
— Адам Фокс,

3
Як це створить нескінченний цикл? Це з опису loadView в документації для iOS. "Контролер перегляду викликає цей метод, коли його властивість подання запитується, але в даний час нульова."
— Йохан

2
Посилання self.view всерединуloadView()- це те, що призводить до нескінченної рекурсії. Навпаки, установка подання не тільки дозволена, але й справді потрібна (вручну або шляхом прив’язки доsuper. В іншому випадку вона буде викликатись до тих пір, поки перегляд будеnil).
— Ніколас Міарі

29

Info.plist

додайте в налаштування безпеки транспорту Info.plist

 <key>NSAppTransportSecurity</key>
 <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
 </dict>

Xcode 9.1+

Використання конструктора інтерфейсів

Ви можете знайти елемент WKWebView в бібліотеці об’єктів.

введіть тут опис зображення

Додайте подання програмно за допомогою Swift 5

let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true

Програмне додавання подання за допомогою Swift 5 (повний зразок)

import UIKit
import WebKit

class ViewController: UIViewController {

    private weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        initWebView()
        webView.loadPage(address: "http://apple.com")
    }

    private func initWebView() {
        let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
        view.addSubview(webView)
        self.webView = webView
        webView.translatesAutoresizingMaskIntoConstraints = false
        webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
    }
}

extension WKWebView {
    func loadPage(address url: URL) { load(URLRequest(url: url)) }
    func loadPage(address urlString: String) {
        guard let url = URL(string: urlString) else { return }
        loadPage(address: url)
    }
}

Не рекомендується виділяти нове подання в ініціалізаторі для WebView. Відповідь crx_au вища
— Іліас Карім

Я не знайшов жодної іншої речі, яка працює !! Отже ... як сказав ILI4S, можливо, це не гарна пропозиція, я не знаю, це чи ні, але працює належним чином! Дякую, ти врятував мій день !! :)
— Хорхе Кордеро

20

З Xcode 8 це тепер можливо, але спосіб досягнення цього - це, м’яко кажучи, трохи невдало. Але привіт, робоче рішення - це робоче рішення, так? Дозволь пояснити.

InitWithCoder WKWebView: більше не коментується як "NS_UNAVAILABLE". Тепер це виглядає так, як показано нижче.

- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

Почніть з підкласу WKWebView та перевизначте initWithCoder. Замість виклику супер initWithCoder вам потрібно буде використовувати інший метод init, такий як initWithFrame: configuration :. Короткий приклад нижче.

- (instancetype)initWithCoder:(NSCoder *)coder
{
    // An initial frame for initialization must be set, but it will be overridden 
    // below by the autolayout constraints set in interface builder. 
    CGRect frame = [[UIScreen mainScreen] bounds];
    WKWebViewConfiguration *myConfiguration = [WKWebViewConfiguration new];

    // Set any configuration parameters here, e.g.
    // myConfiguration.dataDetectorTypes = WKDataDetectorTypeAll; 

    self = [super initWithFrame:frame configuration:myConfiguration];

    // Apply constraints from interface builder.
    self.translatesAutoresizingMaskIntoConstraints = NO;

    return self;
}

У своїй Раскадровці використовуйте UIView і надайте йому власний клас вашого нового підкласу. Решта - звичайна справа (встановлення обмежень на автоматичне розміщення, прив’язка подання до розетки в контролері тощо).

Нарешті, WKWebView масштабує вміст інакше, ніж UIWebView. Багато людей, швидше за все, захочуть дотримуватися простих порад щодо придушення WKWebView від масштабування вмісту до відтворення з таким самим збільшенням, як це робить UIWebView, щоб зробити WKWebView більш уважно стежити за поведінкою UIWebView у цьому відношенні.


2
він також повинен читатись, self = [super initWithFrame:myFrame configuration:myConfiguration];якщо ви використовуєте обмеження, не забудьте встановитиself.translatesAutoresizingMaskIntoConstraints = NO;
— Mojo66

Замість того, щоб використовувати межі головного екрану як кадр-заповнювач, ви також можете використовувати CGRectZero та зберегти собі якийсь код.
— Іліас Карім

Гарне рішення. Працює добре.
— Рейфлек

Працює бездоганно! Гарне виправлення для того, щоб не потрібно націлювати iOS 11, щоб отримати обмеження WKWebView у розкадровці.
— mikemike396 01.03.18

20

Ось проста версія Swift 3, заснована на чудовій відповіді crx_au .

import WebKit

class WKWebView_IBWrapper: WKWebView {
    required convenience init?(coder: NSCoder) {
        let config = WKWebViewConfiguration()
        //config.suppressesIncrementalRendering = true //any custom config you want to add
        self.init(frame: .zero, configuration: config)
        self.translatesAutoresizingMaskIntoConstraints = false
    }
}

Створіть UIView у Interface Builder, призначте свої обмеження та призначте його WKWebView_IBWrapperяк власний клас, наприклад:

Службові програми -> Вкладка Інспектор особи [1]


Відмінна відповідь
— Амр Хоссам

6

Якщо ви все ще стикаєтеся з цією проблемою в останніх версіях Xcode, тобто v9.2 +, просто імпортуйте Webkit у ваш ViewController:

#import <WebKit/WebKit.h>
  1. Перед виправленням: введіть тут опис зображення

  2. Після виправлення:

введіть тут опис зображення


4

Зараз це, мабуть, виправлено в Xcode 9b4. У примітках до випуску сказано: "WKWebView доступний в бібліотеці об'єктів iOS".

Я ще не заглядав глибше, щоб зрозуміти, чи потрібен йому iOS 11, чи він ще не сумісний.


Я можу підтвердити, що це працює! Ура! Він також працює в раскадровках macOS (принаймні для програм, орієнтованих на macOS 10.13+).
— Кліфтон Лабрум

1

Ви можете створити екземпляр та налаштувати WKWebView у IB, починаючи з Xcode 9, не потрібно робити це в коді. введіть тут опис зображення

Зверніть увагу, що ваша ціль розгортання повинна бути вищою, ніж iOS 10, хоча ви отримаєте помилку під час компіляції.

введіть тут опис зображення


0

У версії XCode версії 9.0.1 WKWebView доступний у Interface Builder.



0

Не впевнений, чи допомагає це, але я вирішив проблему замість мене, включивши для цільової програми WebKit. Не вставляйте його, просто посилайте посилання. Я все ще використовую об’єкт WebView в IB і опускаю його на ViewController, у який я його вбудовую, і у мене ніколи не було проблем ...

Зараз я працював над 4 проектами WKWebView MacOS, і WebView працював належним чином у кожному проекті.


-14

Це працювало для мене в Xcode 7.2 ...

Спочатку додайте веб-перегляд як розетку UIWebView в розкадруванні / IB. Це дасть вам таку властивість:

@property (weak, nonatomic) IBOutlet UIWebView *webView;

Потім просто відредагуйте свій код, щоб змінити його на WKWebView.

@property (weak, nonatomic) IBOutlet WKWebView *webView;

Вам також слід змінити спеціальний клас на WKWebView в інспекторі посвідчень.


Я спробував це з проектом OS X - це не працює, тому це має бути особливий випадок для iOS.
— henrikstroem

2
Те, що ви робите, подібно до набору тексту. Він взагалі НЕ може змінити тип webView.
— DawnSong
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.