WKWebView в интерфейсе Builder

Кажется, что шаблоны объектов IB в XCode 6 beta все еще создают объекты старого стиля (UIWebView для iOS и WebView для OSX). Надеюсь, Apple обновит их для современного WebKit, но до тех пор, какой лучший способ создать WKWebViews в Interface Builder? Должен ли я создать базовое представление (UIView или NSView) и присвоить его тип WKWebView? Большинство примеров, которые я нахожу в Интернете, добавляются в контейнерный вид программно; почему-то лучше?

Ответ 1

Вы правы - это не работает. Если вы посмотрите в заголовках, вы увидите:

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

что означает, что вы не можете создать экземпляр одного из ниба.

Вам придется делать это вручную в viewDidLoad или loadView.

Ответ 2

Как указано некоторыми, с 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)
        }
    }
}

Ответ 3

Info.plist

добавьте в настройки безопасности транспорта Info.plist

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

Xcode 9. 1+

Использование конструктора интерфейса

Вы можете найти элемент WKWebView в библиотеке объектов.

enter image description here

Добавить представление программно с помощью 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

Add view programmatically with Swift 5 (full sample)

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

Ответ 4

С Xcode 8 это теперь возможно, но средства достижения этого немного наименее взломаны. Но эй, рабочее решение - это рабочее решение, верно? Позвольте мне объяснить.

WKWebView initWithCoder: больше не аннотируется как "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 в в этом отношении.

Ответ 5

Здесь простая версия 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 как пользовательский класс, например:

Utilities -> Identity Inspector Tab[1]

Ответ 6

Теперь это, по-видимому, исправлено в Xcode 9b4. В примечаниях к выпуску говорится: "WKWebView доступен в библиотеке объектов iOS".

Я не смотрел глубже, чтобы узнать, требует ли он iOS 11 или обратно совместим.

Ответ 7

Если вы все еще сталкиваетесь с этой проблемой в последних версиях XCode, т.е. v9. 2+, просто импортируйте Webkit в свой ViewController:

#import <WebKit/WebKit.h>
  1. До исправления: enter image description here

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

enter image description here

Ответ 8

Вы можете создавать и настраивать WKWebView в IB начиная с Xcode 9, нет необходимости делать это в коде. enter image description here

Обратите внимание, что ваша цель развертывания должна быть выше, чем iOS 10, иначе вы получите ошибку во время компиляции.

enter image description here

Ответ 9

В XCode версии 9.0.1 WKWebView доступен в Interface Builder.

Ответ 10

Я связал WebKit, теперь он работает!

example

Ответ 11

Это работало для меня в Xcode 7.2...

Сначала добавьте веб-представление в качестве выхода UIWebView в раскадровку /IB. Это даст вам следующее свойство:

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

Затем просто измените свой код, чтобы изменить его на WKWebView.

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

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