Cara Mengonfigurasi Penghalaan WKWebView untuk Menyokong Universal Links iOS

opoinstall
2026-10-07
5 min read

Bagaimanakah cara saya mendayakan Universal Links di dalam WKWebView iOS? Universal Links sudah boleh diselesaikan daripada pautan yang layak di dalam WKWebView. Melaksanakan WKNavigationDelegate membolehkan aplikasi hos menyesuaikan polisi penghalaan—memintas destinasi milik aplikasi, mengawal serahan luaran melalui decidePolicyForNavigationAction, dan menguatkuasakan keselamatan pada peringkat bingkai.

Dalam seni bina aplikasi iOS, pemintasan navigasi WKWebView membolehkan aplikasi hos menyesuaikan polisi penghalaan merentas Universal Links, skema URL tersuai, dan destinasi web. Dengan menilai metadata permintaan navigasi dalam WKNavigationDelegate, aplikasi boleh menghalakan destinasi milik aplikasi secara dalaman, menyerahkan sasaran luaran kepada pengendali sistem, dan menguatkuasakan polisi keselamatan peringkat bingkai.

Istilah Definisi Entiti Berkaitan Peranan Niat Carian
WebView Komponen paparan berasaskan WebKit terbenam yang memaparkan kandungan web interaktif di dalam aplikasi iOS. iOS SDK Maklumat / Komersial
Universal Links Mekanisme HTTPS standard yang memautkan domain web yang disahkan kepada paparan aplikasi iOS asli. Penghalaan Deep Link Teknikal / Maklumat
Skema URL Tersuai Skema URI yang ditentukan oleh aplikasi untuk menghalakan URL ke dalam aplikasi asli. Deep Linking Mudah Alih Maklumat

Bagaimanakah Interaksi WKWebView dan Penghalaan Universal Link Berfungsi pada iOS

WKNavigationDelegate memutuskan sama ada WebKit dimuatkan, dihalakan secara dalaman, diserahkan, atau dibatalkan.

Kitaran Hayat Navigasi WebKit dan Polisi Penghalaan Milik Aplikasi

Apple melaksanakan Universal Links sebagai mekanisme penghalaan peringkat sistem yang disokong merentas persekitaran Safari dan WKWebView. Apabila pengguna menekan pautan yang layak di dalam WKWebView terbenam, platform boleh menyelesaikan perkaitan domain dan menghalakan pelaksanaan mengikut polisi sistem pengendalian.

Walaupun Universal Links yang diiktiraf sistem boleh menyerahkan pelaksanaan kepada pengendali asli, persekitaran pelayar terbenam sering memerlukan logik penghalaan khusus aplikasi. Contohnya, apabila pautan menyasarkan domain aplikasi hos itu sendiri, pembangun sering lebih suka menavigasi terus melalui pengawal paparan asli tanpa mencetuskan pelancaran semula aplikasi luaran sepenuhnya. Melaksanakan WKNavigationDelegate memberikan kawalan terperinci kepada aplikasi hos ke atas penilaian pautan, membolehkan pasukan menguatkuasakan senarai kebenaran tersuai dan menghalakan destinasi dalaman dengan boleh diramal.

Halangan Pengalaman Pengguna: Apabila Pelayaran Web Dalam Aplikasi Memerangkap Pengguna dalam Gelung Ubah Hala Web

WebView terbenam sering digunakan untuk menghoskan mikrolaman promosi, pusat bantuan, katalog rakan kongsi, dan halaman pendaratan pemasaran di dalam aplikasi iOS. Apabila halaman web dalam aplikasi menyertakan pautan yang bertujuan untuk menavigasi pengguna ke bahagian lain aplikasi hos (contohnya, butang “Lihat dalam Apl”) atau ke aplikasi rakan kongsi, navigasi lalai boleh membawa kepada pemaparan berlebihan:

  • Pemaparan Web Berlebihan: Daripada memaparkan pengawal paparan asli, pengguna mungkin diberikan versi web responsif halaman dalam aplikasi, yang memerlukan pengesahan berulang dan merendahkan konsistensi visual.
  • Perangkap Web: Pengguna boleh terperangkap dalam tindanan navigasi web yang dalam tanpa cara intuitif untuk kembali ke antara muka aplikasi asli utama.
  • Transisi Apl-ke-Apl yang Gagal: Menekan pautan yang menghala ke perkhidmatan pihak ketiga (seperti aplikasi navigasi, dialog perkongsian sosial, atau gerbang pembayaran) memerlukan penyerahan eksplisit jika perkhidmatan tersebut bergantung pada skema URL tersuai.

Membandingkan WKWebView dengan SFSafariViewController untuk Serahan Web-ke-Apl

Apabila mereka bentuk pelayaran web dalam aplikasi pada iOS, pasukan kejuruteraan mesti memilih antara WKWebView dan SFSafariViewController:

  • SFSafariViewController: Menyediakan antara muka pelayaran Safari yang diuruskan oleh sistem dan serba lengkap dengan ciri-ciri seperti AutoFill dan penyekatan kandungan. Aplikasi hos tidak boleh memeriksa aktiviti pelayaran atau data tapak web, dan penyesuaian UI terhad kepada warna ton.
  • WKWebView: Komponen paparan terbenam yang dihoskan dalam proses UI aplikasi semasa menjalankan kandungan web dalam proses WebKit yang berasingan. Ia membolehkan penyesuaian UI yang mendalam, jambatan JavaScript, dan integrasi susun atur tersuai, yang memerlukan pelaksanaan eksplisit WKNavigationDelegate untuk menyesuaikan polisi penghalaan dan mengendalikan skema tersuai yang ditakrifkan oleh aplikasi.

Bagaimanakah decidePolicyForNavigationAction Memintas Penghalaan WebKit

Saluran Paip Polisi Navigasi: Memahami WKNavigationAction, request, dan decisionHandler

Untuk mengawal aliran navigasi di dalam WKWebView, pembangun menetapkan perwakilan tersuai yang mematuhi Panduan Pembangun Apple mengenai WKNavigationDelegate. Titik pemintasan utama ialah kaedah perwakilan:

func webView(
    _ webView: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
)

Tindakan navigasi yang dicetuskan oleh interaksi pengguna, ubah hala programatik, atau penyerahan borang melalui kaedah ini. Objek WKNavigationAction menyediakan metadata utama:

  • navigationAction.request.url: URL sasaran yang diminta.
  • navigationAction.navigationType: Jenis pencetus (.linkActivated, .other, .formSubmitted).
  • navigationAction.sourceFrame: Maklumat mengenai bingkai yang memulakan permintaan navigasi.
  • navigationAction.targetFrame: Maklumat mengenai bingkai destinasi di mana kandungan bertujuan untuk dimuatkan.

decisionHandler ialah penutup penyiapan yang memberitahu WebKit sama ada untuk membenarkan atau membatalkan navigasi yang diminta.

Bilakah perlu memulangkan .allow vs .cancel: Mengawal Kitaran Hayat Pemuatan Sumber WebKit

WKNavigationActionPolicy yang diserahkan kepada decisionHandler mengawal sama ada WebKit meneruskan navigasi:

  • .allow: Memberitahu WebKit untuk meneruskan navigasi yang diminta di dalam paparan web.
  • .cancel: Mengarahkan WebKit untuk membatalkan navigasi yang diminta. Polisi ini dilaksanakan apabila aplikasi hos memintas skema tersuai, menghalakan Universal Link milik aplikasi secara dalaman, atau menyerahkan sasaran luaran kepada UIApplication.shared.open().

decisionHandler mesti dipanggil tepat sekali bagi setiap tindakan navigasi untuk memastikan resolusi polisi navigasi diteruskan tanpa terhenti.

Menilai Jenis Navigasi: Membezakan Klik Pengguna (.linkActivated) daripada Ubah Hala Automatik

WKNavigationAction.navigationType membolehkan pembangun membezakan interaksi pengguna eksplisit daripada skrip automatik:

  • .linkActivated: Pengguna secara fizikal menekan tag anchor HTML (<a href="...">).
  • .other: Mewakili navigasi programatik, seperti kemas kini window.location.href, muat semula meta, atau panggilan webView.load() awal.
  • .formSubmitted / .formResubmitted: Mewakili penyerahan borang POST atau GET.

Menilai navigationType membolehkan aplikasi menguatkuasakan polisi pautan eksplisit peringkat aplikasi yang konservatif. Untuk pemanggilan skema tersuai luaran atau serahan aplikasi pihak ketiga, memerlukan .linkActivated sebagai gerbang polisi membantu menghalang skrip latar belakang yang tidak dipromosikan daripada mencetuskan pelancaran aplikasi luaran secara automatik.

Mengendalikan Polisi Keputusan Asinkronus Tanpa Kitaran Retain

Apabila pengesahan laluan atau semakan kebenaran memerlukan pertanyaan cache tempatan atau pengesah keselamatan sebelum memulangkan keputusan:

  1. Pastikan decisionHandler dilaksanakan merentas semua laluan pelaksanaan, termasuk keadaan ralat dan pengawal.
  2. Gunakan rujukan lemah ([weak self]) dalam penutup melarikan diri untuk menghalang kitaran retain antara WKWebView, perwakilannya, dan UIViewController induk.

Membezakan Domain Berkaitan Apl Hos daripada Universal Links Luaran

Universal Links milik aplikasi harus mengesahkan dan menghala secara dalaman daripada WKWebView.

Mengurus Destinasi Milik Aplikasi vs. Penyerahan Pautan Peringkat Sistem

Untuk laluan milik aplikasi, elakkan mencuba untuk masuk semula ke aplikasi yang sama melalui carian Universal Link yang berlebihan. Kendalikan destinasi milik aplikasi terus melalui penghala dalaman aplikasi hos, dan gunakan pembukaan sistem terutamanya untuk destinasi yang harus meninggalkan aplikasi semasa atau diselesaikan oleh perkhidmatan luaran.

Pemisahan seni bina ini memastikan navigasi yang lancar:

  • Domain Berkaitan Apl Hos: Jika hos URL sepadan dengan domain berkaitan aplikasi hos itu sendiri (app.example.com), batalkan navigasi paparan web (decisionHandler(.cancel)), sahkan laluan laluan, dan serahkan parameter yang dihurai terus kepada penghala navigasi dalaman aplikasi.
  • Aplikasi Luaran: Jika URL menghala ke destinasi rakan kongsi luaran atau skema tersuai yang dibenarkan, gunakan gerbang pautan eksplisit peringkat aplikasi (navigationType == .linkActivated), batalkan navigasi paparan web, dan majukan permintaan kepada UIApplication.shared.open(url) untuk membiarkan sistem pengendalian melancarkan aplikasi luaran.

Membina Pengesahan Laluan Dalaman: Mengekstrak Laluan dan Parameter Pertanyaan melalui AppRouteValidator

Apabila URL masuk sepadan dengan domain berkaitan aplikasi hos, rentetan URL mesti melalui pengesah laluan yang ketat sebelum mencetuskan transisi pengawal paparan.

Model AppRouteValidator:

  • Mengesahkan laluan URL terhadap senarai kebenaran laluan dalaman yang disokong (contohnya, /open/, /product/, /promo/, /checkout/).
  • Mengekstrak parameter pertanyaan (contohnya, id, promo, utm_source).
  • Menguatkuasakan sekatan set aksara, had panjang, dan penolakan kunci pendua, mengembalikan struktur data ValidatedAppRoute yang bersih.

Mengendalikan Universal Links Pihak Ketiga Luaran melalui Penyerahan UIApplication Sistem

Universal Links Luaran boleh mencuba serahan asli dan kembali ke web.

Apabila halaman web di dalam WKWebView memaut ke perkhidmatan luaran (seperti aplikasi rakan kongsi, platform sosial, atau utiliti luaran), aplikasi hos boleh menyerahkan penghalaan kepada sistem iOS:

let options: [UIApplication.OpenExternalURLOptionsKey: Any] = [
    .universalLinksOnly: true
]
UIApplication.shared.open(url, options: options) { success in
    if !success {
        // Polisi aplikasi fallback: muatkan destinasi web jika tiada aplikasi asli mengendalikan Universal Link
    }
}

Menggunakan .universalLinksOnly sebagai polisi aplikasi memastikan bahawa pengguna hanya dipindahkan ke luar aplikasi semasa jika aplikasi asli yang disahkan dipasang untuk mengendalikan Universal Link.

Mengurus Fallback Skema URL Tersuai (myapp://) Bersama HTTPS Universal Links

Walaupun HTTPS Universal Links mewakili deep linking standard pada iOS, skema tersuai yang ditentukan aplikasi (myapp:// atau partnerapp://) kekal biasa merentas kempen promosi dan integrasi rakan kongsi.

Dalam pelaksanaan WKNavigationDelegate yang disatukan:

  • Skema bukan HTTP/HTTPS diperiksa terlebih dahulu. Jika skema sepadan dengan protokol tersuai yang dibenarkan dan memenuhi polisi pautan eksplisit (navigationType == .linkActivated), perwakilan mengesahkan hos, laluan, dan parameter sebelum menghantar kepada UIApplication.shared.open().
  • Skema yang tidak dikenali atau pemanggilan skema latar belakang yang tidak dipromosikan dibatalkan serta-merta, menghalang ralat navigasi yang tidak dikendalikan atau banjir niat didorong skrip.
[Pengguna Berinteraksi dengan Pautan di dalam WKWebView iOS]
                       │
                       ▼
[WKNavigationDelegate: decidePolicyForNavigationAction]
                       │
         ┌─────────────┴─────────────┐
         ▼                           ▼
[!action.sourceFrame.isMainFrame] [action.sourceFrame.isMainFrame]
         │                           │
         ▼                           ▼
[Gerbang Keselamatan Subbingkai] [Periksa Skema & Hos Destinasi]
├─ HTTP(S) -> .allow                 │
└─ Bukan-Web -> .cancel  ┌───────────┼───────────┐
   (Sekat Subbingkai)    ▼           ▼           ▼
                   [Domain Hos] [Web Luaran] [Skema Tersuai]
                         │           │           │
                         ▼           ▼           ▼
                   [AppRoute]    [Periksa Pautan] [Periksa Pautan]
                   ├─ Sah ->     ├─ Rakan ->   ├─ Sah & Klik ->
                   │  Dalaman    │  Buka Apl    │  Buka Apl
                   └─ Tidak sah-> └─ Web ->      └─ Tidak sah/Auto->
                      .cancel       .allow         .cancel

Cara Menguatkuasakan Keselamatan Bingkai Utama dan Menghalang Hijacking Iframe

Konteks asal bingkai dan sasaran WKNavigationAction menentukan polisi navigasi yang selamat.

Melayan Navigasi Web Terbenam sebagai Input Tidak Dipercayai: Standard Keselamatan Deep Link OWASP

Selaras dengan Panduan Ujian Keselamatan Aplikasi Mudah Alih OWASP mengenai Deep Link Tidak Selamat, semua URL dan beban parameter yang diproses oleh pengendali navigasi mudah alih mesti dianggap sebagai input luaran yang tidak dipercayai.

Halaman web yang dipaparkan dalam WKWebView mungkin memuatkan skrip pihak ketiga, sepanduk pengiklanan, atau kandungan yang dijana pengguna. Jika perwakilan navigasi memajukan URL sewenang-wenangnya kepada pengawal paparan asli atau UIApplication.shared.open() tanpa pengesahan, parameter yang tidak dijangka boleh menyasarkan laluan aplikasi dalaman yang sensitif.

Mengasingkan Navigasi Bingkai Utama daripada Iframe Terbenam dan Sasaran Tetingkap Baharu

Selaras dengan Dokumentasi Pembangun Apple mengenai WKNavigationAction, menilai keselamatan bingkai memerlukan semakan bingkai yang memulakan:

  • sourceFrame.isMainFrame == true: Navigasi dimulakan terus oleh bingkai dokumen peringkat atas utama.
  • sourceFrame.isMainFrame == false: Navigasi dimulakan oleh subbingkai terbenam atau iframe.
  • targetFrame == nil: Navigasi meminta sasaran tetingkap baharu (seperti anchor dengan target="_blank").

Untuk menghalang hijacking iframe—di mana iframe terbenam cuba melancarkan aplikasi luaran atau mencetuskan transisi paparan asli di latar belakang—perwakilan mesti menilai sourceFrame.isMainFrame. Jika bingkai yang memulakan ialah iframe (sourceFrame.isMainFrame == false), benarkan navigasi subbingkai HTTP/HTTPS standard (.allow), tetapi sekat sebarang skema tersuai bukan web atau serahan penghalaan asli (.cancel).

Menghalang Pemanggilan Protokol Subbingkai Berbahaya dan Banjir Skema Latar Belakang

Menguatkuasakan semakan bingkai memulakan menghalang subbingkai daripada mencetuskan pemanggilan skema luaran yang tidak dipromosikan:

if !navigationAction.sourceFrame.isMainFrame {
    let scheme = url.scheme?.lowercased() ?? ""
    if scheme == "http" || scheme == "https" {
        decisionHandler(.allow) // Benarkan navigasi subbingkai HTTP(S) standard
    } else {
        decisionHandler(.cancel) // Sekat skema bukan web daripada subbingkai
    }
    return
}

Menguatkuasakan Senarai Kebenaran Laluan dan Parameter Pertanyaan yang Ketat dalam Penghalaan Pelanggan

Kedua-dua URL domain berkaitan dalaman dan skema tersuai luaran mesti melalui model pengesah yang ketat sebelum pelaksanaan:

  • Senarai Kebenaran Awalan Laluan: Menguatkuasakan awalan laluan yang diluluskan (contohnya, /open/, /product/, /promo/, /checkout/), menolak laluan sewenang-wenangnya atau yang rosak.
  • Penapisan Kunci Pertanyaan: Buang kunci pertanyaan yang tidak dijangka dan tolak kunci parameter pendua untuk menghalang pencemaran parameter.
  • Kekangan Jenis-Data & Panjang: Sekat nilai parameter kepada set aksara abfanumerik dan kuatkan had panjang maksimum (≤64\le 64 aksara).

Pelaksanaan WKNavigationDelegate Pengeluaran dalam Swift

Menstrukturkan Seni Bina CustomWebViewController dan Perwakilan dalam Swift

Pengawal WKWebView pengeluaran menyelaraskan konfigurasi web, penilaian polisi navigasi, penghalaan dalaman, dan serahan luaran. Pelaksanaan ini merangkumkan peraturan pengesahan dalam kelas pengesah khusus (AppRouteValidator dan CustomSchemeValidator) untuk memastikan panggilan balik perwakilan bersih, boleh diuji, dan selamat.

Melaksanakan Model AppRouteValidator dan CustomSchemeValidator

Model pengesah menguatkuasakan keselamatan fail-tutup yang ketat:

  • AppRouteValidator mengesahkan domain berkaitan dalaman, menyemak awalan laluan dan membersihkan parameter pertanyaan ke dalam objek ValidatedAppRoute yang berstruktur.
  • CustomSchemeValidator mengesahkan skema tersuai yang dibenarkan (myapp), mengesahkan hos yang dibenarkan (open, product, event), dan membersihkan nilai pertanyaan.

OpoInstall boleh diintegrasikan bersama lapisan penghalaan milik aplikasi untuk atribusi dan pemulihan parameter tertunda. Semak dokumentasi integrasi SDK untuk panduan integrasi yang komprehensif.

Pelaksanaan teknikal di bawah menunjukkan cara mengonfigurasi WKNavigationDelegate yang selamat dalam Swift:

// iOS: CustomWebViewController dengan Penghalaan WKNavigationDelegate yang Ketat dan Keselamatan Bingkai
// Contoh integrasi rujukan. Sahkan tandatangan kaedah dan pemetaan domain terhadap seni bina yang anda gunakan.
import UIKit
import WebKit

struct ValidatedAppRoute {
    let path: String
    let queryParams: [String: String]
}

// 1. Pengesah untuk Domain Berkaitan Aplikasi Hos (Laluan Dalaman)
class AppRouteValidator {
    private static let allowedPrefixes = ["/open/", "/product/", "/promo/", "/checkout/"]
    private static let allowedQueryKeys = Set(["target", "id", "promo", "utm_source"])

    static func validate(url: URL) -> ValidatedAppRoute? {
        let path = url.path
        // Kuatkan senarai kebenaran awalan laluan yang diluluskan
        guard allowedPrefixes.contains(where: { path.hasPrefix($0) }) else {
            return nil
        }

        var sanitizedParams: [String: String] = [:]
        var seenKeys = Set<String>()

        if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
           let queryItems = components.queryItems {
            let validChars = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-")
            
            for item in queryItems {
                // Pengesahan fail-tutup: tolak URL jika kunci pertanyaan tidak dibenarkan atau kunci pendua wujud
                guard allowedQueryKeys.contains(item.name), !seenKeys.contains(item.name) else { return nil }
                seenKeys.insert(item.name)

                let value = item.value ?? ""
                if value.count <= 64 && value.rangeOfCharacter(from: validChars.inverted) == nil {
                    sanitizedParams[item.name] = value
                } else {
                    return nil
                }
            }
        }

        return ValidatedAppRoute(path: path, queryParams: sanitizedParams)
    }
}

// 2. Pengesah untuk Skema Tersuai Luaran (myapp://)
class CustomSchemeValidator {
    private static let allowedSchemes = Set(["myapp"])
    private static let allowedHosts = Set(["open", "product", "event"])
    private static let allowedPathPrefixes = ["/detail/", "/view/", "/main/"]
    private static let allowedQueryKeys = Set(["target", "id", "promo", "utm_source"])

    static func validate(url: URL) -> URL? {
        guard let scheme = url.scheme?.lowercased(), allowedSchemes.contains(scheme) else {
            return nil
        }
        guard let host = url.host?.lowercased(), allowedHosts.contains(host) else {
            return nil
        }

        let path = url.path
        if !path.isEmpty && !allowedPathPrefixes.contains(where: { path.hasPrefix($0) }) {
            return nil
        }

        var seenKeys = Set<String>()
        if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
           let queryItems = components.queryItems {
            let validChars = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-")
            for item in queryItems {
                guard allowedQueryKeys.contains(item.name), !seenKeys.contains(item.name) else { return nil }
                seenKeys.insert(item.name)

                let value = item.value ?? ""
                if value.count > 64 || value.rangeOfCharacter(from: validChars.inverted) != nil {
                    return nil
                }
            }
        }

        return url
    }
}

// 3. UIViewController Menghoskan WKWebView dengan Pemintasan Polisi Navigasi yang Selamat
class CustomWebViewController: UIViewController, WKNavigationDelegate {

    var webView: WKWebView!
    private let hostAssociatedDomain = "app.example.com"
    private let allowedExternalPartnerHosts = Set(["partner.example.com"])

    override func viewDidLoad() {
        super.viewDidLoad()

        let configuration = WKWebViewConfiguration()
        webView = WKWebView(frame: view.bounds, configuration: configuration)
        webView.navigationDelegate = self
        view.addSubview(webView)
    }

    func webView(
        _ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
    ) {
        guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }

        // Semakan Keselamatan 1: Kuatkan sempadan bingkai memulakan (sourceFrame) untuk menghalang hijacking iframe
        if !navigationAction.sourceFrame.isMainFrame {
            let scheme = url.scheme?.lowercased() ?? ""
            if scheme == "http" || scheme == "https" {
                decisionHandler(.allow) // Benarkan navigasi subbingkai HTTP(S) standard
            } else {
                decisionHandler(.cancel) // Sekat skema bukan web daripada subbingkai/iframe
            }
            return
        }

        let scheme = url.scheme?.lowercased() ?? ""
        let isExplicitLinkActivation = (navigationAction.navigationType == .linkActivated)

        // Semakan Keselamatan 2: Kendalikan Domain Berkaitan Apl Hos Sendiri
        // Hala secara dalaman daripada memanggil UIApplication.shared.open
        if scheme == "https", let host = url.host?.lowercased(), host == hostAssociatedDomain {
            if let validatedRoute = AppRouteValidator.validate(url: url) {
                AppInternalRouter.shared.navigate(to: validatedRoute)
            }
            decisionHandler(.cancel) // Batalkan pemuatan dalam-webview untuk menghala secara dalaman
            return
        }

        // Semakan Keselamatan 3: Kendalikan Skema Tersuai yang Dibenarkan (myapp://) dengan Polisi Pengaktifan-Pautan
        if scheme != "http" && scheme != "https" && scheme != "about" {
            // Kuatkan bahawa pelancaran aplikasi luaran skema tersuai memerlukan pengaktifan pautan pengguna eksplisit
            if isExplicitLinkActivation, let validatedURL = CustomSchemeValidator.validate(url: url) {
                UIApplication.shared.open(validatedURL, options: [:], completionHandler: nil)
            }
            decisionHandler(.cancel) // Batalkan pemuatan dalam-webview untuk menghalang ralat skema yang tidak dikendalikan
            return
        }

        // Semakan Keselamatan 4: Kendalikan Destinasi Luaran dan Permintaan Tetingkap-Baharu (target="_blank")
        if scheme == "http" || scheme == "https" {
            let host = url.host?.lowercased() ?? ""
            
            // Serahkan Universal Links rakan kongsi yang disahkan kepada aplikasi luaran dengan polisi pautan eksplisit
            if allowedExternalPartnerHosts.contains(host) && isExplicitLinkActivation {
                let options: [UIApplication.OpenExternalURLOptionsKey: Any] = [
                    .universalLinksOnly: true
                ]
                UIApplication.shared.open(url, options: options) { [weak self] success in
                    if !success {
                        // Polisi aplikasi fallback: muatkan destinasi rakan kongsi luaran di dalam paparan web jika tiada aplikasi asli mengendalikannya
                        guard let self = self else { return }
                        self.webView.load(navigationAction.request)
                    }
                }
                decisionHandler(.cancel)
                return
            }

            // Jika targetFrame adalah nil (permintaan tetingkap baharu), muatkan dengan selamat ke dalam webView semasa
            if navigationAction.targetFrame == nil {
                webView.load(navigationAction.request)
                decisionHandler(.cancel)
                return
            }

            // Kandungan web standard terus dimuatkan di dalam WKWebView
            decisionHandler(.allow)
            return
        }

        decisionHandler(.allow)
    }
}

// Pemegang tempat penghala dalaman khusus aplikasi (bukan API SDK OpoInstall)
class AppInternalRouter {
    static let shared = AppInternalRouter()

    func navigate(to route: ValidatedAppRoute) {
        // Laksanakan transisi pengawal paparan UI dalaman berdasarkan laluan dan parameter pertanyaan
    }
}

Pelaksanaan Selamat-Utas: Memastikan Transisi UI Dilaksanakan pada Pelakon Utama (Main Actor)

Dalam model konkurensi Swift semasa, panggilan balik WKNavigationDelegate diasingkan kepada pelakon utama. Penghalaan aplikasi dan transisi pengawal paparan dilaksanakan pada pelakon utama, mengekalkan keselamatan utas merentas aliran kerja navigasi asli.

Ralat Navigasi Deep Link WKWebView dan Matriks Diagnostik

Panduan Penyelesaian Masalah Deep Linking WKWebView iOS Komprehensif

Matriks di bawah menggariskan mod kegagalan biasa yang dihadapi apabila mengurus deep link dan skema tersuai di dalam WKWebView iOS, berserta punca utama dan remedi kejuruteraan yang disyorkan:

Tandatangan / Gejala Ralat Punca Utama Versi iOS Berkenaan Titik Semakan Diagnostik Remedi Disyorkan
Universal Link Dimuatkan dalam Web Domain milik aplikasi tidak dipintas iOS 9+ decidePolicyForNavigationAction tidak dikendalikan Pintas domain hos, hurai laluan, hala secara dalaman, .cancel
Pautan Domain-Sendiri Gagal Dihala Memanggil UIApplication.open pada domain sendiri iOS 9+ UIApplication.shared.open dipanggil pada hos sendiri Elakkan pembukaan sendiri luaran; hala ke penghala dalaman terus
Skema Tersuai Gagal Secara Senyap Protokol bukan-HTTP WebKit tidak dikenali iOS 9+ Skema tidak diserahkan kepada UIApplication Pintas skema dalam perwakilan, sahkan senarai kebenaran, buka melalui UIApplication
Hijacking Protokol Iframe Subbingkai mencetuskan skema tersuai luaran iOS 9+ sourceFrame.isMainFrame tidak disemak Kawal dengan if !sourceFrame.isMainFrame dan sekat skema bukan web
Masalah Amaran atau Transisi Handoff UI Transisi UI dilaksanakan di luar utas utama iOS 9+ Tiada penghantaran pelakon-utama Pastikan pelaksanaan pelakon-utama untuk penghala dalaman dan transisi pengawal paparan

Soalan Lazim (FAQ)

Bagaimanakah pembangun boleh memintas Universal Links dalam WKWebView?
Pembangun melaksanakan `WKNavigationDelegate` dan memeriksa URL masuk di dalam `decidePolicyForNavigationAction`. Jika URL sepadan dengan destinasi milik aplikasi, perwakilan membatalkan navigasi dalam-webview dengan `.cancel` dan menyerahkan parameter yang disahkan terus kepada penghala dalaman aplikasi.
Bolehkah saya menggunakan UIApplication.shared.open untuk melancarkan aplikasi saya sendiri daripada WKWebView?
Dokumentasi Apple menyatakan bahawa memanggil `UIApplication.shared.open()` pada Universal Link yang menghala ke domain berkaitan milik aplikasi hos tidak akan membuka pautan dalam aplikasi sebagai Universal Link. Untuk pautan domain-sendiri, aplikasi harus membatalkan navigasi webview dan memanggil penghala navigasi dalamannya secara terus.
Bagaimanakah cara saya menghalang iframe terbenam dalam WKWebView daripada mencetuskan pelancaran aplikasi luaran?
Untuk menghalang hijacking iframe, semak `navigationAction.sourceFrame.isMainFrame` di dalam `decidePolicyForNavigationAction`. Jika `isMainFrame` adalah `false`, benarkan navigasi subbingkai HTTP(S) standard dengan `.allow`, tetapi batalkan skema tersuai bukan-web dengan `.cancel` untuk menghalang iframe pihak ketiga daripada melaksanakan pelancaran luaran yang tidak dipromosikan.

Ringkasan dan Rangka Kerja Keputusan

Mengendalikan Universal Links dan skema tersuai di dalam WKWebView iOS memerlukan merapatkan sempadan antara bekas pemaparan web WebKit dan kitaran hayat navigasi UIKit asli. Bergantung pada polisi navigasi lalai boleh menghalang serahan yang lancar apabila logik penghalaan milik aplikasi diperlukan.

Dengan melaksanakan WKNavigationDelegate yang teguh yang mengesahkan sempadan bingkai, menguatkuasakan polisi pengaktifan-pautan konservatif pada serahan luaran, menghurai domain berkaitan dalaman melalui pengesah laluan yang ketat, dan menyerahkan sasaran luaran dengan selamat kepada UIApplication.shared.open, pasukan kejuruteraan mengekalkan navigasi terkawal sambil melindungi daripada hijacking protokol iframe.

Untuk meneroka seni bina deep linking dan penghalaan parameter iOS asli, rujuk dokumentasi integrasi SDK.

Bahan Berkaitan

Share this article