WKWebView trong Trình tạo giao diện


95

Có vẻ như các mẫu đối tượng IB trong XCode 6 beta vẫn đang tạo các đối tượng kiểu cũ (UIWebView cho iOS và WebView cho OSX). Hy vọng rằng Apple sẽ cập nhật chúng cho WebKit hiện đại, nhưng cho đến lúc đó, cách tốt nhất để tạo WKWebViews trong Interface Builder là gì? Tôi có nên tạo chế độ xem cơ bản (UIView hoặc NSView) và gán loại của nó cho WKWebView không? Hầu hết các ví dụ tôi tìm thấy trên mạng đều thêm nó vào chế độ xem vùng chứa theo chương trình; là tốt hơn vì một số lý do?



4
Tôi đang sử dụng Xcode 7.2, tôi không thấy WKWebView trong thư viện đối tượng. Nó vẫn không có sẵn?
user3731622

10
Vẫn không có mặt trong Xcode 8.
Ryan Ballantyne

1
Xcode 9.0.1 hiện hỗ trợ WKWebView trong IB. Tất cả các câu trả lời ở đây hiện không được dùng nữa.
smileBot

1
@smileBot Phiên bản mới của Xcode không có WKWebView nhưng nó yêu cầu bạn nhắm mục tiêu iOS 11+. Câu trả lời crx_au hoạt động tốt nhất -> stackoverflow.com/a/40118654/757503
mikemike396 Ngày

Câu trả lời:


70

Bạn đã đúng - nó dường như không hoạt động. Nếu bạn nhìn vào các tiêu đề, bạn sẽ thấy:

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

điều này ngụ ý rằng bạn không thể khởi tạo một cái từ ngòi.

Bạn sẽ phải làm điều đó bằng tay trong viewDidLoad hoặc loadView.


Hy vọng rằng họ sẽ thay đổi điều đó vào một lúc nào đó, nhưng tôi cho rằng đó không phải là vấn đề lớn. Johan chỉ cho tôi quay lại video WWDC, và thậm chí chúng đang khởi tạo bằng mã.
Adam Fox

3
Về phía cộng, làm nó trong mã sẽ cho phép bạn sử dụng UIWebView trong iOS 7 và WKWebView trong iOS 8.
EricS

Sau câu trả lời này, tôi nghĩ bạn có thể ghi đè phương thức này trong một lớp con của WKWebView và sau đó sử dụng nó trong trình tạo giao diện .. nhưng không có super.initWithCoder .. hãy thử nghiệm! :)
zarghol

1
Sau một thử nghiệm cá nhân: bạn không thể ... "Không thể ghi đè 'init' mà đã được đánh dấu không có sẵn" quá xấu ...
zarghol

2
Một điều hợp lý cần làm có thể là tạo một chế độ xem phụ UIView được gọi là MyWebView có WKWebView hoặc UIWebView làm chế độ xem phụ, được xác định trong thời gian chạy trong initWithCoder. Sau đó, bạn có thể tạo chế độ xem MyWebView trong IB. Nếu bạn đang sử dụng Swift, bạn thậm chí có thể thêm các thuộc tính có thể được chỉnh sửa trong IB bằng từ khóa IBInspectable.
EricS

65

Như đã chỉ ra bởi một số người, kể từ Xcode 6.4, WKWebView vẫn không có sẵn trên Trình tạo giao diện. Tuy nhiên, rất dễ dàng thêm chúng qua mã.

Tôi chỉ sử dụng cái này trong ViewController của mình. Trình tạo giao diện bỏ qua

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
Câu hỏi này đặc biệt về Trình tạo giao diện, vì vậy câu trả lời này không hữu ích lắm.
Steve Landey

5
Bạn đúng rồi. Đáng lẽ tôi phải bắt đầu câu trả lời bằng “Bạn không thể tạo WKWebView từ IB” :) Nhưng tôi xem video phiên “Giới thiệu API WebKit hiện đại” từ WWDC và họ đang sử dụng Xcode nên tôi đoán rằng đây chỉ là thứ không có ' t có sẵn cho chúng tôi vào lúc này.
Johan

1
Chỉ cần xem lại video và họ đang khởi tạo WKWebView bằng mã. Đó là khoảng 17:20 trong video.
Adam Fox

3
Nó sẽ tạo ra một vòng lặp vô hạn như thế nào? Đây là từ mô tả của loadView trong tài liệu iOS. "View controller gọi phương thức này khi thuộc tính view của nó được yêu cầu nhưng hiện tại là nil."
Johan

2
Tham chiếu self.view bên trongloadView()là thứ dẫn đến đệ quy vô hạn. Mặt khác, việc đặt chế độ xem không chỉ được cho phép mà còn thực sự bắt buộc (theo cách thủ công hoặc bằng cách xâu chuỗi đếnsuper. Nếu không, nó sẽ tiếp tục được gọi miễn là chế độ xem đónil).
Nicolas Miari

29

Info.plist

thêm vào cài đặt bảo mật truyền tải Info.plist của bạn

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

Xcode 9.1+

Sử dụng trình tạo giao diện

Bạn có thể tìm thấy phần tử WKWebView trong thư viện Đối tượng.

nhập mô tả hình ảnh ở đây

Thêm chế độ xem theo chương trình với 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

Thêm chế độ xem theo chương trình với Swift 5 (mẫu đầy đủ)

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

Đó không phải là một gợi ý hay để phân bổ một chế độ xem mới trong trình khởi tạo WebView. phản ứng crx_au là vượt trội
Ilias Karim

Tôi không tìm thấy bất kỳ thứ nào khác hoạt động !! Vì vậy, ... như ILI4S đã nói có thể đó không phải là một gợi ý tốt, tôi không biết nó có hay không, nhưng hoạt động đúng! Cảm ơn người đàn ông, bạn đã cứu ngày của tôi !! :)
Jorge Cordero

20

Với Xcode 8, điều này hiện có thể thực hiện được, nhưng ít nhất thì phương tiện để đạt được nó hơi khó. Nhưng này, một giải pháp làm việc là một giải pháp làm việc, phải không? Hãy để tôi giải thích.

InitWithCoder của WKWebView: không còn được chú thích là "NS_UNAVAILABLE". Bây giờ nó trông như hình dưới đây.

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

Bắt đầu bằng cách phân lớp con WKWebView và ghi đè initWithCoder. Thay vì gọi super initWithCoder, bạn sẽ cần sử dụng một phương thức init khác, chẳng hạn như initWithFrame: configuration :. Ví dụ nhanh bên dưới.

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

Trong Bảng phân cảnh của bạn, hãy sử dụng UIView và cung cấp cho nó một lớp tùy chỉnh của lớp con mới của bạn. Phần còn lại là kinh doanh như bình thường (thiết lập các ràng buộc bố cục tự động, liên kết chế độ xem với một ổ cắm trong bộ điều khiển, v.v.).

Cuối cùng, WKWebView chia tỷ lệ nội dung khác với UIWebView. Nhiều người có thể sẽ muốn làm theo lời khuyên đơn giản trong Suppress WKWebView từ việc chia tỷ lệ nội dung để hiển thị ở mức độ phóng đại tương tự như UIWebView để làm cho WKWebView theo sát hành vi UIWebView hơn về mặt này.


2
nó nên đọc self = [super initWithFrame:myFrame configuration:myConfiguration];còn nếu bạn sử dụng hạn chế, đừng quên để thiết lậpself.translatesAutoresizingMaskIntoConstraints = NO;
Mojo66

Thay vì sử dụng các giới hạn của màn hình chính làm khung giữ chỗ, bạn cũng có thể sử dụng CGRectZero và lưu cho mình một số mã.
Ilias Karim

Giải pháp tốt. Hoạt động tốt.
Rayfleck

Hoạt động hoàn hảo! Bản sửa lỗi tuyệt vời để không phải Nhắm mục tiêu iOS 11 để có được các ràng buộc WKWebView trong bảng phân cảnh.
mikemike396

20

Đây là một phiên bản Swift 3 đơn giản dựa trên câu trả lời tuyệt vời của 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
    }
}

Tạo một UIView trong Trình tạo giao diện, gán các ràng buộc của bạn và gán nó WKWebView_IBWrappernhư một lớp tùy chỉnh, như sau:

Tiện ích -> Tab Trình kiểm tra danh tính [1]


Tuyệt vời câu trả lời
Amr Hossam

6

Nếu bạn vẫn gặp sự cố này trong các phiên bản gần đây của Xcode, tức là v9.2 +, chỉ cần nhập Webkit vào ViewController của bạn:

#import <WebKit/WebKit.h>
  1. Trước khi sửa chữa: nhập mô tả hình ảnh ở đây

  2. Sau khi sửa chữa:

nhập mô tả hình ảnh ở đây


4

Điều này hiện đã được khắc phục trong Xcode 9b4. Ghi chú phát hành cho biết "WKWebView có sẵn trong thư viện đối tượng iOS".

Tôi chưa tìm hiểu sâu hơn để xem liệu nó có yêu cầu iOS 11 hay tương thích ngược hay không.


Tôi có thể xác nhận rằng điều này hoạt động! Hoan hô! Nó cũng hoạt động trong bảng phân cảnh macOS (ít nhất là đối với các ứng dụng nhắm mục tiêu macOS 10.13+).
Clifton Labrum,

1

Bạn có thể khởi tạo và định cấu hình WKWebView trong IB kể từ Xcode 9, không cần thực hiện trong mã. nhập mô tả hình ảnh ở đây

Lưu ý rằng mục tiêu triển khai của bạn phải cao hơn iOS 10 nếu không bạn sẽ gặp lỗi thời gian biên dịch.

nhập mô tả hình ảnh ở đây


0

Trong phiên bản XCode 9.0.1, WKWebView có sẵn trên Trình tạo giao diện.



0

Không chắc liệu điều này có giúp ích gì không nhưng tôi đã giải quyết vấn đề cho mình bằng cách bao gồm khung WebKit cho mục tiêu. Không nhúng nó chỉ liên kết tài liệu tham khảo. Tôi vẫn sử dụng đối tượng WebView trong IB và thả nó vào ViewController mà tôi đang nhúng nó và tôi chưa bao giờ gặp sự cố ...

Tôi đã làm việc trên 4 dự án WKWebView MacOS và WebView đã hoạt động bình thường trong mỗi dự án.


-14

Điều này đã làm việc cho tôi trong Xcode 7.2 ...

Đầu tiên hãy thêm chế độ xem web dưới dạng cửa hàng UIWebView trong bảng phân cảnh / IB. Điều này sẽ cung cấp cho bạn một tài sản như thế này:

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

Sau đó, chỉ cần chỉnh sửa mã của bạn để thay đổi nó thành WKWebView.

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

Bạn cũng nên thay đổi lớp tùy chỉnh thành WKWebView trong trình kiểm tra Danh tính.


Tôi đã thử điều này với một dự án OS X - điều đó không hoạt động, vì vậy nó phải là trường hợp đặc biệt cho iOS.
henrikstroem

2
Những gì bạn làm giống như kiểu nhập liệu. Nó KHÔNG thể thay đổi kiểu của webView.
DawnSong
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.