diff --git a/init_darwin.m b/init_darwin.m index c7be20df..b1d88c39 100644 --- a/init_darwin.m +++ b/init_darwin.m @@ -40,6 +40,11 @@ @end +// we are not in control of the actual lifetimes and refcounts of NSViews (see http://stackoverflow.com/a/29523141/3408572) +// when we're done with a view, it'll be added as a subview of this one, and this one will be released on application shutdown +// we need this separate view because it's possible for controls to have no parent but still be alive +NSView *deletedControlsView; + uiInitOptions options; const char *uiInit(uiInitOptions *o) @@ -50,6 +55,10 @@ const char *uiInit(uiInitOptions *o) // see https://github.com/andlabs/ui/issues/6 [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp setDelegate:[uiAppDelegate new]]; + + // we can use a stock NSView for this + deletedControlsView = [[NSView alloc] initWithFrame:NSZeroRect]; + return NULL; } diff --git a/newcontrol_darwin.m b/newcontrol_darwin.m index f53ef584..1fff8a82 100644 --- a/newcontrol_darwin.m +++ b/newcontrol_darwin.m @@ -10,12 +10,11 @@ struct singleView { uintptr_t parent; }; -// TODO this will need to change if we want to provide removal static void singleDestroy(uiControl *c) { singleView *s = (singleView *) (c->internal); - [s->view removeFromSuperview]; + [deletedControlsView addSubview:s->immediate]; } static uintptr_t singleHandle(uiControl *c) @@ -99,6 +98,9 @@ uiControl *uiDarwinNewControl(Class class, BOOL inScrollView, BOOL scrollViewHas s->immediate = (NSView *) (s->scrollView); } + // and keep a reference to s->immediate for when we remove the control from its parent + [s->immediate retain]; + c = uiNew(uiControl); c->internal = s; c->destroy = singleDestroy; @@ -115,7 +117,8 @@ BOOL uiDarwinControlFreeWhenAppropriate(uiControl *c, NSView *newSuperview) { singleView *s = (singleView *) (c->internal); - if (newSuperview == nil) { + if (newSuperview == deletedControlsView) { + [s->immediate release]; // we don't need the reference anymore uiFree(s); uiFree(c); return YES; diff --git a/uipriv_darwin.h b/uipriv_darwin.h index 057af1dc..e34b8256 100644 --- a/uipriv_darwin.h +++ b/uipriv_darwin.h @@ -24,6 +24,9 @@ fprintf(stderr, "%p free\n", self); \ } +// init_darwin.m +extern NSView *deletedControlsView; + // util_darwin.m extern void setStandardControlFont(NSControl *); extern void disableAutocorrect(NSTextView *);