From 4d1e0ddb9dce4dbc4187dd1f23d794ebfa51c718 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 12 Oct 2022 15:42:16 -0400 Subject: [PATCH] Support NAME on WebViewDelegate trait impls --- examples/browser/main.rs | 4 +++- src/webview/class.rs | 4 ++-- src/webview/mod.rs | 3 ++- src/webview/traits.rs | 11 +++++++++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/browser/main.rs b/examples/browser/main.rs index e6433fc..8033360 100644 --- a/examples/browser/main.rs +++ b/examples/browser/main.rs @@ -91,7 +91,9 @@ impl Dispatcher for BasicApp { #[derive(Default)] pub struct WebViewInstance; -impl WebViewDelegate for WebViewInstance {} +impl WebViewDelegate for WebViewInstance { + const NAME: &'static str = "BrowserWebViewDelegate"; +} struct AppWindow { toolbar: Toolbar, diff --git a/src/webview/class.rs b/src/webview/class.rs index e6da759..507ebf4 100644 --- a/src/webview/class.rs +++ b/src/webview/class.rs @@ -185,8 +185,8 @@ pub fn register_webview_class() -> *const Class { /// Registers an `NSViewController` that we effectively turn into a `WebViewController`. Acts as /// both a subclass of `NSViewController` and a delegate of the held `WKWebView` (for the various /// varieties of delegates needed there). -pub fn register_webview_delegate_class() -> *const Class { - load_or_register_class("NSObject", "RSTWebViewDelegate", |decl| unsafe { +pub fn register_webview_delegate_class(instance: &T) -> *const Class { + load_or_register_class("NSObject", instance.subclass_name(), |decl| unsafe { decl.add_ivar::(WEBVIEW_DELEGATE_PTR); // WKNavigationDelegate diff --git a/src/webview/mod.rs b/src/webview/mod.rs index 9c9f1ad..1161068 100644 --- a/src/webview/mod.rs +++ b/src/webview/mod.rs @@ -230,10 +230,11 @@ where /// Initializes a new WebView with a given `WebViewDelegate`. This enables you to respond to events /// and customize the view as a module, similar to class-based systems. pub fn with(config: WebViewConfig, delegate: T) -> WebView { + let delegate_class = register_webview_delegate_class(&delegate); let mut delegate = Box::new(delegate); let objc_delegate = unsafe { - let objc_delegate: id = msg_send![register_webview_delegate_class::(), new]; + let objc_delegate: id = msg_send![delegate_class, new]; let ptr: *const T = &*delegate; (&mut *objc_delegate).set_ivar(WEBVIEW_DELEGATE_PTR, ptr as usize); ShareId::from_ptr(objc_delegate) diff --git a/src/webview/traits.rs b/src/webview/traits.rs index 06bc2ea..fc9d221 100644 --- a/src/webview/traits.rs +++ b/src/webview/traits.rs @@ -8,6 +8,17 @@ use crate::webview::WebView; /// You can implement this on structs to handle callbacks from the underlying `WKWebView`. pub trait WebViewDelegate { + /// Used to cache subclass creations on the Objective-C side. + /// You can just set this to be the name of your delegate type. This + /// value *must* be unique per-type. + const NAME: &'static str; + + /// You should rarely (read: probably never) need to implement this yourself. + /// It simply acts as a getter for the associated `NAME` const on this trait. + fn subclass_name(&self) -> &'static str { + Self::NAME + } + /// Called when the View is ready to work with. You're passed a `ViewHandle` - this is safe to /// store and use repeatedly, but it's not thread safe - any UI calls must be made from the /// main thread!