Reputation: 348
Full project can be seen here (for context: https://github.com/atlas-engineer/next-cocoa)
The following code returns EXC_BAD_ACCESS:
- (bool)windowClose:(NSString *)key
{
NSWindow *window = [[self windows] objectForKey:key];
[[self windows] removeObjectForKey:key];
[window close];
return YES;
}
The following code, however, works
- (bool)windowClose:(NSString *)key
{
[[self windows] removeObjectForKey:key];
return YES;
}
As does the following:
- (bool)windowClose:(NSString *)key
{
NSWindow *window = [[self windows] objectForKey:key];
[window close];
return YES;
}
It is only somehow when you put them together that everything breaks.
For reference, I've provided the AutokeyDictionary implementation below, which is the value of [self windows]
in the examples above
//
// AutokeyDictionary.m
// next-cocoa
//
// Created by John Mercouris on 3/14/18.
// Copyright © 2018 Next. All rights reserved.
//
#import "AutokeyDictionary.h"
@implementation AutokeyDictionary
@synthesize elementCount;
- (instancetype) init
{
self = [super init];
if (self)
{
[self setElementCount:0];
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (NSString *) insertElement:(NSObject *) object
{
NSString *elementKey = [@([self elementCount]) stringValue];
[_dict setValue:object forKey: elementKey];
[self setElementCount:[self elementCount] + 1];
return elementKey;
}
- (NSUInteger)count {
return [_dict count];
}
- (id)objectForKey:(id)aKey {
return [_dict objectForKey:aKey];
}
- (void)removeObjectForKey:(id)aKey {
return [_dict removeObjectForKey:aKey];
}
- (NSEnumerator *)keyEnumerator {
return [_dict keyEnumerator];
}
- (NSArray*)allKeys {
return [_dict allKeys];
}
@end
Lastly, for the record, turning on zombies does make the code work, though that is obviously not a solution.
Upvotes: 0
Views: 55
Reputation: 348
The correct answer ended up being the following sequence of code
- (bool)windowClose:(NSString *)key
{
NSWindow *window = [[self windows] objectForKey:key];
[window setReleasedWhenClosed:NO];
[window close];
[[self windows] removeObjectForKey:key];
return YES;
}
any other order of events and the object would be prematurely released.
Upvotes: 0
Reputation: 90571
Your window's releasedWhenClosed
property is probably defaulting to YES
, which is likely to conflict with ARC's memory management. Set it to NO
when you create the window.
Upvotes: 2