Interface BuilderのWKWebView


95

XCode 6ベータのIBオブジェクトテンプレートは、古いスタイルのオブジェクト(iOSのUIWebViewとOSXのWebView)を作成しているようです。Appleが最新のWebKitに合わせてそれらを更新することを願っていますが、それまでは、Interface BuilderでWKWebViewを作成する最良の方法は何ですか?基本ビュー(UIViewまたはNSView)を作成し、そのタイプをWKWebViewに割り当てる必要がありますか?オンラインで見つけたほとんどの例は、プログラムでコンテナビューに追加しています。なんらかの理由でそれは良いですか?


3
これはまだ未解決のバグです。lists.webkit.org
David H

4
Xcode 7.2を使用していますが、オブジェクトライブラリにWKWebViewが表示されません。まだ利用できませんか?
user3731622

10
Xcode 8にはまだ存在しません
Ryan Ballantyne '22

1
Xcode 9.0.1がIBのWKWebViewをサポートするようになりました。ここでのすべての回答は非推奨になりました。
smileBot

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
プラス側では、コードでそれを行うと、あなたはiOSの8中のiOS 7とWKWebViewでのUIWebViewを使用できるようになる
EricS

この回答の後、WKWebViewのサブクラスでこのメソッドをオーバーライドして、インターフェイスビルダーで使用できると思いますが、super.initWithCoderを使用しないでテストしてみましょう。:)
zarghol 2015年

1
個人的なテスト後:次のことはできません...「使用不可とマークされた「init」をオーバーライドできません」あまりにも悪い...
zarghol

2
実行する合理的なことの1つは、実行時にinitWithCoderで決定されるWKWebViewまたはUIWebViewのいずれかをサブビューとして持つ、MyWebViewと呼ばれるUIViewサブビューを作成することです。次に、IBでMyWebViewビューを作成できます。Swiftを使用している場合は、IBInspectableキーワードを使用して、IBで編集できるプロパティを追加することもできます。
EricS 2015年

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に関するものなので、この回答はあまり役に立ちません。
Steve Landey、2014年

5
あなたが正しいです。私は「IBからWKWebViewを作成することはできません」で答えを始めるべきでした:)しかし、WWDCからのセッションビデオ「Introducing the Modern WebKit API」を見て、彼らはXcodeを使用しているので、これは単なる何かだと思います現在利用できます。
ヨハン

1
ビデオをもう一度チェックアウトしたところ、彼らはWKWebViewをコードでインスタンス化しています。動画の17時20分頃です。
アダムフォックス

3
どのようにして無限ループを作成しますか?これは、iOSドキュメントのloadViewの説明からです。「ビューコントローラーは、ビュープロパティが要求されたが現在はnilのときにこのメソッドを呼び出します。」
ヨハン

2
self.view内部loadView()での参照は無限再帰につながるものです。一方、ビューの設定は許可されているだけでなく実際に必要です(手動で、またはにチェーンすることによってsuper。それ以外の場合は、ビューがである限り、呼び出され続けますnil)。
Nicolas Miari

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の応答は優れています
Ilias Karim

私はうまくいく他のものを見つけませんでした!! だから... ILI4Sが言ったように、それは良い提案ではないかもしれませんが、そうかどうかはわかりませんが、正しく機能します!おかげで、あなたは私の日を救った!! :)
ホルヘ・コルデロ

20

Xcode 8ではこれが可能になりましたが、それを達成する手段は控えめに言っても少し厄介です。しかし、ねえ、実用的なソリューションは実用的なソリューションですよね?説明させてください。

WKWebViewのinitWithCoder:は「NS_UNAVAILABLE」として注釈されなくなりました。次のようになります。

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

WKWebViewをサブクラス化して開始し、initWithCoderをオーバーライドします。スーパーinitWithCoderを呼び出す代わりに、initWithFrame:configuration:などの別のinitメソッドを使用する必要があります。以下の簡単な例。

- (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の動作をより厳密にするためにUIWebViewが行うように、コンテンツをスケーリングして同じ倍率でレンダリングすることからSuppress WKWebViewの簡単なアドバイスに従いたいと思うでしょう。


2
self = [super initWithFrame:myFrame configuration:myConfiguration];制約を使用する場合は、必ず読む必要があります。設定することを忘れないでくださいself.translatesAutoresizingMaskIntoConstraints = NO;
Mojo66

メイン画面の境界をプレースホルダーフレームとして使用するのではなく、CGRectZeroを使用してコードを保存することもできます。
Ilias Karim

素晴らしい解決策。うまくいきます。
Rayfleck

完璧に動作します!ストーリーボードでWKWebView制約を取得するためにiOS 11をターゲットにする必要がないための素晴らしい修正。
mikemike396 2018年

20

crx_auの優れた回答に基づくシンプルなSwift 3バージョンを以下に示します。

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

次のように、Interface BuilderでUIViewを作成し、制約を割り当て、それWKWebView_IBWrapperをカスタムクラスとして割り当てます。

ユーティリティ-> Identity Inspectorタブ[1]


すばらしい答え
Amr Hossam 2017

6

Xcodeの最近のバージョン、つまりv9.2 +でもこの問題が解決しない場合は、WebkitをViewControllerにインポートするだけです。

#import <WebKit/WebKit.h>
  1. 修正前: ここに画像の説明を入力してください

  2. 修正後:

ここに画像の説明を入力してください


4

これは明らかにXcode 9b4で修正されています。リリースノートには、「WKWebViewはiOSオブジェクトライブラリで使用できます」と記載されています。

iOS 11が必要か、下位互換性があるかについては、まだ詳しく調べていません。


これが機能することを確認できます!やったー!また、macOSストーリーボードでも機能します(少なくともmacOS 10.13以降を対象とするアプリの場合)。
Clifton Labrum

1

Xcode 9以降、IBでWKWebViewをインスタンス化して構成できます。コードで行う必要はありません。 ここに画像の説明を入力してください

ただし、展開ターゲットはiOS 10よりも高くする必要があります。そうしないと、コンパイル時エラーが発生します。

ここに画像の説明を入力してください


0

XCodeバージョン9.0.1では、WKWebViewはInterface Builderで使用できます。



0

これが役立つかどうかはわかりませんが、ターゲットのWebKitフレームワークを含めることで問題を解決しました。参照をリンクするだけで埋め込んではいけません。私はまだIBでWebViewオブジェクトを使用しており、それを埋め込んでいるViewControllerにドロップします。問題は一度もありません...

私は現在4つのWKWebView MacOSプロジェクトで作業しており、WebViewは各プロジェクトで適切に機能しています。


-14

これはXcode 7.2で私のために働きました...

最初に、ストーリーボード/ IBのUIWebViewアウトレットとしてWebビューを追加します。これにより、次のようなプロパティが得られます。

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

次に、コードを編集してWKWebViewに変更します。

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

また、IDインスペクターでカスタムクラスをWKWebViewに変更する必要があります。


私はこれをOS Xプロジェクトで試しました-うまくいかないので、iOSの場合は特別なケースになるはずです。
henrikstroem

2
あなたがすることは、型キャストのようなものです。webViewのタイプはまったく変更できません。
DawnSong 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.