From 34b02b28b52e38c165ef3d805d22aeead8afd53f Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Tue, 24 Mar 2020 21:42:07 -0700 Subject: [PATCH] On dropping a View, which is the originating View, we check to see if there's a superview and remove it if so --- appkit/view/mod.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/appkit/view/mod.rs b/appkit/view/mod.rs index 7965973..1f33888 100644 --- a/appkit/view/mod.rs +++ b/appkit/view/mod.rs @@ -12,7 +12,7 @@ use objc_id::ShareId; use objc::runtime::{Class, Object}; use objc::{msg_send, sel, sel_impl}; -use crate::foundation::{id, YES, NO, NSArray, NSString}; +use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::color::Color; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::pasteboard::PasteboardType; @@ -209,10 +209,20 @@ impl Layout for View { } impl Drop for View { - /// A bit of extra cleanup for delegate callback pointers. + /// A bit of extra cleanup for delegate callback pointers. If the originating `View` is being + /// dropped, we do some logic to release the loopback ptr. We also go ahead and check to see if + /// this has a superview (i.e, it's in the heirarchy) on the AppKit side. If it does, we go + /// ahead and remove it - this is intended to match the semantics of how Rust handles things. + /// + /// There are, thankfully, no delegates we need to break here. fn drop(&mut self) { if let Some(ptr) = &self.internal_callback_ptr { unsafe { + let superview: id = msg_send![&*self.objc, superview]; + if superview != nil { + let _: () = msg_send![&*self.objc, removeFromSuperview]; + } + let _ = Rc::from_raw(ptr); } }