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.