WKWebView ในตัวสร้างอินเทอร์เฟซ


95

ดูเหมือนว่าเทมเพลตอ็อบเจ็กต์ IB ใน XCode 6 beta ยังคงสร้างอ็อบเจ็กต์แบบเก่า (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
— Ryan Ballantyne

1
Xcode 9.0.1 รองรับ WKWebView ใน IB แล้ว คำตอบทั้งหมดที่นี่เลิกใช้แล้ว
— 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 และแม้ว่าพวกเขากำลังสร้างอินสแตนซ์ในโค้ด
— Adam Fox

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 โดยเฉพาะดังนั้นคำตอบนี้จึงไม่มีประโยชน์มากนัก
— Steve Landey

5
คุณพูดถูก ฉันควรจะเริ่มคำตอบด้วย“ คุณไม่สามารถสร้าง WKWebView จาก IB ได้” :) แต่ฉันดูวิดีโอเซสชัน“ การแนะนำ Modern WebKit API” จาก WWDC และพวกเขาใช้ Xcode ดังนั้นฉันจึงเดาว่านี่เป็นเพียงสิ่งที่ไม่ใช่ ไม่มีให้เราในขณะนี้
— Johan

1
เพิ่งตรวจสอบวิดีโออีกครั้งและพวกเขากำลังสร้างอินสแตนซ์ WKWebView ในโค้ด เวลาประมาณ 17:20 น. ในวิดีโอ
— Adam Fox

3
มันจะสร้างวงวนไม่สิ้นสุดได้อย่างไร? นี่มาจากคำอธิบายของ loadView ในเอกสาร iOS "ตัวควบคุมมุมมองเรียกใช้เมธอดนี้เมื่อมีการร้องขอคุณสมบัติมุมมอง แต่ปัจจุบันเป็นศูนย์"
— โยฮั

2
การอ้างอิง self.viewภายในloadView()เป็นสิ่งที่นำไปสู่การเรียกซ้ำที่ไม่มีที่สิ้นสุด ในทางกลับกันการตั้งค่ามุมมองไม่ได้รับอนุญาตเท่านั้น แต่จำเป็นต้องใช้จริง ๆ(ด้วยตนเองหรือโดยการเชื่อมโยงกับsuperมิฉะนั้นจะถูกเรียกไปเรื่อย ๆ ตราบเท่าที่มุมมองนั้นเป็นnil)
— Nicolas Miari

30

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 บอกอาจจะไม่ใช่คำแนะนำที่ดีฉันไม่รู้ว่าใช่หรือไม่ แต่ทำงานได้ถูกต้อง! ขอบคุณมากคุณช่วยวันของฉัน !! :)
— Jorge Cordero

20

ด้วย Xcode 8 ตอนนี้เป็นไปได้ แต่วิธีการบรรลุเป้าหมายนั้นเป็นเรื่องที่แฮ็คเล็กน้อยที่จะพูดน้อยที่สุด แต่เดี๋ยวก่อนโซลูชันที่ใช้งานได้คือโซลูชันที่ใช้งานได้จริงไหม? ให้ฉันอธิบาย

initWithCoder ของ WKWebView: ไม่มีคำอธิบายประกอบเป็น "NS_UNAVAILABLE" อีกต่อไป ตอนนี้มีลักษณะดังที่แสดงด้านล่าง

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

เริ่มต้นด้วยคลาสย่อย WKWebView และแทนที่ initWithCoder แทนที่จะเรียก super 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;
}

ใน Storyboard ของคุณใช้ UIView และให้คลาสที่กำหนดเองสำหรับคลาสย่อยใหม่ของคุณ ส่วนที่เหลือเป็นธุรกิจตามปกติ (การตั้งค่าข้อ จำกัด การจัดวางอัตโนมัติการเชื่อมโยงมุมมองกับเต้าเสียบในคอนโทรลเลอร์ ฯลฯ )

สุดท้าย WKWebView จะปรับขนาดเนื้อหาให้แตกต่างจาก UIWebView หลายคนน่าจะต้องการทำตามคำแนะนำง่ายๆในSuppress WKWebView จากการปรับขนาดเนื้อหาไปจนถึงการแสดงผลที่กำลังขยายเช่นเดียวกับที่ UIWebView ทำเพื่อให้ WKWebView ติดตามพฤติกรรม UIWebView อย่างใกล้ชิดยิ่งขึ้นในเรื่องนี้


2
ควรอ่านself = [super initWithFrame:myFrame configuration:myConfiguration];ด้วยหากคุณใช้ข้อ จำกัด อย่าลืมตั้งค่าself.translatesAutoresizingMaskIntoConstraints = NO;
— Mojo66

แทนที่จะใช้ขอบเขตของหน้าจอหลักเป็นกรอบตัวยึดคุณอาจใช้ CGRectZero และบันทึกรหัสด้วยตัวคุณเอง
— Ilias Karim

ทางออกที่ดี ทำได้ดี.
— Rayfleck

ทำงานได้อย่างไม่มีที่ติ! การแก้ไขที่ดีที่ไม่ต้องกำหนดเป้าหมาย iOS 11 เพื่อรับข้อ จำกัด WKWebView ในกระดานเรื่องราว
— mikemike396

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 ในตัวสร้างอินเทอร์เฟซกำหนดข้อ จำกัด ของคุณและกำหนดWKWebView_IBWrapperเป็นคลาสที่กำหนดเองดังนี้:

ยูทิลิตี้ -> แท็บตัวตรวจสอบข้อมูลประจำตัว [1]


คำตอบที่ยอดเยี่ยม
— Amr Hossam

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

คุณสามารถสร้างอินสแตนซ์และกำหนดค่า WKWebView ใน IB ได้ตั้งแต่ Xcode 9 โดยไม่จำเป็นต้องทำในโค้ด ป้อนคำอธิบายภาพที่นี่

โปรดทราบว่าเป้าหมายการปรับใช้ของคุณต้องสูงกว่า iOS 10 ไม่เช่นนั้นคุณจะได้รับข้อผิดพลาดเวลาคอมไพล์

ป้อนคำอธิบายภาพที่นี่




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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.