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.