WKWebView в интерфейсе строителя
похоже, что шаблоны объектов IB в бета-версии XCode 6 все еще создают объекты старого стиля (UIWebView для iOS и WebView для OSX). Надеюсь, Apple обновит их для современного WebKit, но до тех пор, каков лучший способ создать WKWebViews в Interface Builder? Должен ли я создать базовое представление (UIView или NSView) и назначить его тип WKWebView? Большинство примеров, которые я нахожу в интернете, добавляют его в представление контейнера программно; это лучше по какой-то причине?
10 ответов:
вы правы - это, кажется, не работает. Если вы посмотрите в заголовках, вы увидите:
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;
что означает, что вы не можете создать экземпляр из пера.
вы должны будете сделать это вручную в viewDidLoad или loadView.
как указывали некоторые, начиная с 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) } } }
Xcode 9.1
вы можете найти элемент WKWebView в библиотеке объектов.
Swift 3 и Xcode 8
используя раскадровку
ViewController.Свифт
import UIKit import WebKit // Add WKWebView in StoryBoard class ViewController: UIViewController { @IBOutlet var webView: WebView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) webView.loadUrl(string: "http://apple.com") } } class WebView: WKWebView { required init?(coder: NSCoder) { if let _view = UIView(coder: coder) { super.init(frame: _view.frame, configuration: WKWebViewConfiguration()) autoresizingMask = _view.autoresizingMask } else { return nil } } func loadUrl(string: String) { if let url = URL(string: string) { load(URLRequest(url: url)) } } }
Главная.раскадровка
<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_24167812" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0zg-ri-o6Y" customClass="WebView" customModule="stackoverflow_24167812" customModuleProvider="target"> <rect key="frame" x="0.0" y="20" width="375" height="647"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> </view> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </view> <connections> <outlet property="webView" destination="0zg-ri-o6Y" id="G0g-bh-eej"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="140" y="138.98050974512745"/> </scene> </scenes> </document>
программно
import UIKit import WebKit // Add WKWebView programmatically class ViewController: UIViewController { var webView: WKWebView? override func viewDidLoad() { super.viewDidLoad() // init webView webView = WKWebView(frame: view.bounds) view.addSubview(webView!) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // load url webView?.loadUrl(string: "http://apple.com") } } extension WKWebView { func loadUrl(string: String) { if let url = URL(string: string) { load(URLRequest(url: url)) } } }
С Xcode 8 это теперь возможно, но средства достижения этого немного хаки, чтобы не сказать больше. Но эй, рабочее решение-это рабочее решение, верно? Позвольте мне объяснить.
initWithCoder WKWebView: больше не аннотируется как "NS_UNAVAILABLE". Теперь он выглядит так, как показано ниже.
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
начать WKWebView, разделяя на подклассы и переопределить initWithCoder. Вместо вызова super initWithCoder вам нужно будет использовать другой метод init, например initWithFrame:конфигурации:. Быстрый пример ниже.
- (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 в этом отношении.
вот простая версия 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
как пользовательский класс, например:
теперь это, по-видимому, исправлено в Xcode 9b4. В примечаниях к выпуску говорится: "WKWebView доступен в библиотеке объектов iOS."
Я не заглядывал глубже, чтобы увидеть, требует ли он iOS 11 или обратно совместим.
это работает для меня в Xcode 7.2...
Сначала добавьте веб-представление в качестве выхода UIWebView в раскадровке / IB. Это даст вам свойство, как это:
@property (weak, nonatomic) IBOutlet UIWebView *webView;
затем просто изменить свой код, чтобы изменить его на WKWebView.
@property (weak, nonatomic) IBOutlet WKWebView *webView;
вы также должны изменить пользовательский класс на WKWebView в инспекторе идентификации.