diff --git a/src/webview/class.rs b/src/webview/class.rs index 3695392..9dfa251 100644 --- a/src/webview/class.rs +++ b/src/webview/class.rs @@ -4,7 +4,6 @@ use std::ffi::c_void; use std::sync::Once; -use std::rc::Rc; use block::Block; @@ -50,11 +49,8 @@ extern fn on_message(this: &Object, _: Sel, _: id, script_me unsafe { let name = NSString::wrap(msg_send![script_message, name]).to_str(); let body = NSString::wrap(msg_send![script_message, body]).to_str(); - let d = delegate.borrow(); - (*d).on_message(name, body); + delegate.on_message(name, body); } - - Rc::into_raw(delegate); } /// Fires when deciding a navigation policy - i.e, should something be allowed or not. @@ -63,16 +59,10 @@ extern fn decide_policy_for_action(this: &Object, _: Sel, _: let action = NavigationAction::new(action); - { - let d = delegate.borrow(); - - (*d).policy_for_navigation_action(action, |policy| unsafe { - let handler = handler as *const Block<(NSInteger,), c_void>; - (*handler).call((policy.into(),)); - }); - } - - Rc::into_raw(delegate); + delegate.policy_for_navigation_action(action, |policy| unsafe { + let handler = handler as *const Block<(NSInteger,), c_void>; + (*handler).call((policy.into(),)); + }); } /// Fires when deciding a navigation policy - i.e, should something be allowed or not. @@ -81,44 +71,32 @@ extern fn decide_policy_for_response(this: &Object, _: Sel, let response = NavigationResponse::new(response); - { - let d = delegate.borrow(); - - (*d).policy_for_navigation_response(response, |policy| unsafe { - let handler = handler as *const Block<(NSInteger,), c_void>; - (*handler).call((policy.into(),)); - }); - } - - Rc::into_raw(delegate); + delegate.policy_for_navigation_response(response, |policy| unsafe { + let handler = handler as *const Block<(NSInteger,), c_void>; + (*handler).call((policy.into(),)); + }); } /// Fires when deciding a navigation policy - i.e, should something be allowed or not. extern fn run_open_panel(this: &Object, _: Sel, _: id, params: id, _: id, handler: usize) { let delegate = load::(this, WEBVIEW_DELEGATE_PTR); - { - let d = delegate.borrow(); + delegate.run_open_panel(params.into(), move |urls| unsafe { + let handler = handler as *const Block<(id,), c_void>; - (*d).run_open_panel(params.into(), move |urls| unsafe { - let handler = handler as *const Block<(id,), c_void>; + match urls { + Some(u) => { + let nsurls: NSArray = u.iter().map(|s| { + let s = NSString::new(s); + msg_send![class!(NSURL), URLWithString:s.into_inner()] + }).collect::>().into(); - match urls { - Some(u) => { - let nsurls: NSArray = u.iter().map(|s| { - let s = NSString::new(s); - msg_send![class!(NSURL), URLWithString:s.into_inner()] - }).collect::>().into(); + (*handler).call((nsurls.into_inner(),)); + }, - (*handler).call((nsurls.into_inner(),)); - }, - - None => { (*handler).call((nil,)); } - } - }); - } - - Rc::into_raw(delegate); + None => { (*handler).call((nil,)); } + } + }); } /// Called when a download has been initiated in the WebView, and when the navigation policy @@ -131,24 +109,18 @@ extern fn handle_download(this: &Object, _: Sel, download: i let handler = handler as *const Block<(objc::runtime::BOOL, id), c_void>; let filename = NSString::wrap(suggested_filename).to_str(); - { - let d = delegate.borrow(); + delegate.run_save_panel(filename, move |can_overwrite, path| unsafe { + if path.is_none() { + let _: () = msg_send![download, cancel]; + } - (*d).run_save_panel(filename, move |can_overwrite, path| unsafe { - if path.is_none() { - let _: () = msg_send![download, cancel]; - } - - let path = NSString::new(&path.unwrap()); - - (*handler).call((match can_overwrite { - true => YES, - false => NO - }, path.into_inner())); - }); - } - - Rc::into_raw(delegate); + let path = NSString::new(&path.unwrap()); + + (*handler).call((match can_overwrite { + true => YES, + false => NO + }, path.into_inner())); + }); } /// Registers an `NSViewController` that we effectively turn into a `WebViewController`. Acts as diff --git a/src/webview/mod.rs b/src/webview/mod.rs index d1dea3b..7fc9042 100644 --- a/src/webview/mod.rs +++ b/src/webview/mod.rs @@ -13,32 +13,32 @@ //! Apple does not ship `WKWebView` on tvOS, and as a result this control is not provided on that //! platform. -use std::rc::Rc; -use std::cell::RefCell; - use core_graphics::geometry::CGRect; use objc_id::ShareId; use objc::runtime::Object; use objc::{class, msg_send, sel, sel_impl}; -use crate::foundation::{id, YES, NO, NSString}; +use crate::foundation::{id, nil, YES, NO, NSString}; use crate::geometry::Rect; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; -pub mod actions; -pub mod enums; +mod actions; +pub use actions::*; + +mod config; +pub use config::WebViewConfig; + +mod enums; +pub use enums::*; pub(crate) mod class; use class::{register_webview_class, register_webview_delegate_class}; //pub(crate) mod process_pool; -pub mod traits; +mod traits; pub use traits::WebViewDelegate; -pub mod config; -pub use config::WebViewConfig; - pub(crate) static WEBVIEW_DELEGATE_PTR: &str = "rstWebViewDelegatePtr"; fn allocate_webview( @@ -87,12 +87,8 @@ pub struct WebView { /// we do so. pub objc_delegate: Option>, - /// An internal callback pointer that we use in delegate loopbacks. Default implementations - /// don't require this. - pub(crate) internal_callback_ptr: Option<*const RefCell>, - /// A pointer to the delegate for this view. - pub delegate: Option>>, + pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. pub top: LayoutAnchorY, @@ -130,7 +126,6 @@ impl WebView { let view = allocate_webview(config, None); WebView { - internal_callback_ptr: None, delegate: None, objc_delegate: None, top: LayoutAnchorY::new(unsafe { msg_send![view, topAnchor] }), @@ -150,23 +145,18 @@ impl WebView where T: WebViewDelegate + 'static { /// 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 = Rc::new(RefCell::new(delegate)); - - let internal_callback_ptr = { - let cloned = Rc::clone(&delegate); - Rc::into_raw(cloned) - }; + let delegate = Box::new(delegate); let objc_delegate = unsafe { let objc_delegate: id = msg_send![register_webview_delegate_class::(), new]; - (&mut *objc_delegate).set_ivar(WEBVIEW_DELEGATE_PTR, internal_callback_ptr as usize); + let ptr: *const T = &*delegate; + (&mut *objc_delegate).set_ivar(WEBVIEW_DELEGATE_PTR, ptr as usize); ShareId::from_ptr(objc_delegate) }; let view = allocate_webview(config, Some(&objc_delegate)); let mut view = WebView { - internal_callback_ptr: Some(internal_callback_ptr), delegate: None, objc_delegate: Some(objc_delegate), top: LayoutAnchorY::new(unsafe { msg_send![view, topAnchor] }), @@ -180,11 +170,7 @@ impl WebView where T: WebViewDelegate + 'static { objc: unsafe { ShareId::from_ptr(view) }, }; - { - let mut delegate = delegate.borrow_mut(); - (*delegate).did_load(view.clone_as_handle()); - } - + &delegate.did_load(view.clone_as_handle()); view.delegate = Some(delegate); view } @@ -197,7 +183,6 @@ impl WebView { /// delegate - the `View` is the only true holder of those. pub(crate) fn clone_as_handle(&self) -> WebView { WebView { - internal_callback_ptr: None, delegate: None, top: self.top.clone(), leading: self.leading.clone(), @@ -245,14 +230,11 @@ impl std::fmt::Debug for WebView { impl Drop for WebView { /// A bit of extra cleanup for delegate callback pointers. fn drop(&mut self) { - /*println!("... {}", self.delegate.is_some()); - if let Some(delegate) = &self.delegate { - println!("Strong count: {}", Rc::strong_count(&delegate)); - if Rc::strong_count(&delegate) == 1 { - let _ = unsafe { - Rc::from_raw(self.internal_callback_ptr.unwrap()) - }; + if self.delegate.is_some() { + unsafe { + let _: () = msg_send![&*self.objc, setNavigationDelegate:nil]; + let _: () = msg_send![&*self.objc, setUIDelegate:nil]; } - }*/ + } } } diff --git a/src/webview/traits.rs b/src/webview/traits.rs index 4bd614a..2944706 100644 --- a/src/webview/traits.rs +++ b/src/webview/traits.rs @@ -11,7 +11,7 @@ pub trait WebViewDelegate { /// 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! - fn did_load(&mut self, _webview: WebView) {} + fn did_load(&self, _webview: WebView) {} /// Called when this is about to be added to the view heirarchy. fn will_appear(&self) {}