Fix "attempt to destroy map with items inside" when menuManager is deallocated
Fixes #58. The map needs to have its contents properly freed which requires releasing the properly retaining the NSMenuItem object.
This commit is contained in:
parent
abb3c39c78
commit
49e17cbfd7
|
@ -129,7 +129,6 @@ void uiUninit(void)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
uninitMenus();
|
|
||||||
[appDelegate() release];
|
[appDelegate() release];
|
||||||
[realNSApp() setDelegate:nil];
|
[realNSApp() setDelegate:nil];
|
||||||
[realNSApp() release];
|
[realNSApp() release];
|
||||||
|
|
16
darwin/map.m
16
darwin/map.m
|
@ -41,3 +41,19 @@ void mapDelete(struct mapTable *m, void *key)
|
||||||
{
|
{
|
||||||
NSMapRemove(m->m, key);
|
NSMapRemove(m->m, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mapWalk(struct mapTable *m, void (*f)(void *key, void *value))
|
||||||
|
{
|
||||||
|
NSMapEnumerator e = NSEnumerateMapTable(m->m);
|
||||||
|
void *k = NULL;
|
||||||
|
void *v = NULL;
|
||||||
|
while (NSNextMapEnumeratorPair(&e, &k, &v)) {
|
||||||
|
f(k, v);
|
||||||
|
}
|
||||||
|
NSEndMapTableEnumeration(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapReset(struct mapTable *m)
|
||||||
|
{
|
||||||
|
NSResetMapTable(m->m);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,14 @@ enum {
|
||||||
typeSeparator,
|
typeSeparator,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void mapItemReleaser(void *key, void *value)
|
||||||
|
{
|
||||||
|
uiMenuItem *item;
|
||||||
|
|
||||||
|
item = (uiMenuItem *)value;
|
||||||
|
[item->item release];
|
||||||
|
}
|
||||||
|
|
||||||
@implementation menuManager
|
@implementation menuManager
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
|
@ -43,6 +51,9 @@ enum {
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
|
uninitMenus();
|
||||||
|
mapWalk(self->items, mapItemReleaser);
|
||||||
|
mapReset(self->items);
|
||||||
mapDestroy(self->items);
|
mapDestroy(self->items);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
@ -234,16 +245,16 @@ static uiMenuItem *newItem(uiMenu *m, int type, const char *name)
|
||||||
item->type = type;
|
item->type = type;
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case typeQuit:
|
case typeQuit:
|
||||||
item->item = appDelegate().menuManager.quitItem;
|
item->item = [appDelegate().menuManager.quitItem retain];
|
||||||
break;
|
break;
|
||||||
case typePreferences:
|
case typePreferences:
|
||||||
item->item = appDelegate().menuManager.preferencesItem;
|
item->item = [appDelegate().menuManager.preferencesItem retain];
|
||||||
break;
|
break;
|
||||||
case typeAbout:
|
case typeAbout:
|
||||||
item->item = appDelegate().menuManager.aboutItem;
|
item->item = [appDelegate().menuManager.aboutItem retain];
|
||||||
break;
|
break;
|
||||||
case typeSeparator:
|
case typeSeparator:
|
||||||
item->item = [NSMenuItem separatorItem];
|
item->item = [[NSMenuItem separatorItem] retain];
|
||||||
[m->menu addItem:item->item];
|
[m->menu addItem:item->item];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -335,7 +346,6 @@ void uninitMenus(void)
|
||||||
{
|
{
|
||||||
if (menus == NULL)
|
if (menus == NULL)
|
||||||
return;
|
return;
|
||||||
// don't worry about the actual NSMenus and NSMenuItems; they'll be freed when we clean up the NSApplication
|
|
||||||
[menus enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) {
|
[menus enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) {
|
||||||
NSValue *v;
|
NSValue *v;
|
||||||
uiMenu *m;
|
uiMenu *m;
|
||||||
|
|
|
@ -89,6 +89,8 @@ extern void mapDestroy(struct mapTable *m);
|
||||||
extern void *mapGet(struct mapTable *m, void *key);
|
extern void *mapGet(struct mapTable *m, void *key);
|
||||||
extern void mapSet(struct mapTable *m, void *key, void *value);
|
extern void mapSet(struct mapTable *m, void *key, void *value);
|
||||||
extern void mapDelete(struct mapTable *m, void *key);
|
extern void mapDelete(struct mapTable *m, void *key);
|
||||||
|
extern void mapWalk(struct mapTable *m, void (*f)(void *key, void *value));
|
||||||
|
extern void mapReset(struct mapTable *m);
|
||||||
|
|
||||||
// area.m
|
// area.m
|
||||||
extern int sendAreaEvents(NSEvent *);
|
extern int sendAreaEvents(NSEvent *);
|
||||||
|
|
Loading…
Reference in New Issue