realm-swift: EXC_BAD_ACCESS crash when using NSOutlineView
I’m creating an NSOutlineView populated by objects saved on Realm. The object is called Person. And this is how it looks:
@interface Person : RLMObject
@property NSString *name;
@property NSInteger indent;
@property NSInteger order;
// Ignored properties
@property NSArray *contacts;
The contacts array returns a query. Those contacts are child of the person, but they also have the same object class, Person.
And this is the view controller:
#import "MainWindowController.h"
#import "Person.h"
@interface MainWindowController () <NSOutlineViewDataSource, NSOutlineViewDelegate>
@property (strong) IBOutlet NSOutlineView *outlineView;
@property (nonatomic, strong) RLMResults *array;
@property (nonatomic, strong) RLMNotificationToken *notification;
@end
@implementation MainWindowController
- (id)init
{
self = [super initWithWindowNibName:@"MainWindow"];
if (self) {
__weak typeof(self) weakSelf = self;
self.notification = [RLMRealm.defaultRealm addNotificationBlock:^(NSString *note, RLMRealm *realm) {
[weakSelf.outlineView reloadData];
}];
self.array = [[Person objectsWhere:@"indent == 1"] sortedResultsUsingProperty:@"order" ascending:YES];
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
[self.outlineView setRowHeight:50];
}
#pragma mark - NSOutlineView
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if (item == nil) {
return self.array[index];
}
else if ([item isKindOfClass:[Person class]]) {
return [item contacts][index];
}
return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
if (item == nil) {
return NO;
}
else if ([item isKindOfClass:[Person class]]) {
return [item contacts].count > 0;
}
return NO;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if (item == nil) {
return self.array.count;
}
else if ([item isKindOfClass:[Person class]]) {
return [item contacts].count;
}
return 0;
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSView *cellView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 250, 0)];
NSTextField *titleTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 15, 250, 18)];
[titleTextField setEditable:NO];
[titleTextField setBordered:NO];
titleTextField.backgroundColor = [NSColor clearColor];
titleTextField.textColor = [NSColor blackColor];
titleTextField.focusRingType = NSFocusRingTypeNone;
titleTextField.stringValue = [item name];
[cellView addSubview:titleTextField];
return cellView;
}
The “root” cells are displayed correctly, but then, when I click the arrow to expand one of those root cells, the app crashes with an EXC_BAD_ACCESS error. I used NSZombie to know more about this crash, and that’s what it tells me:
-[RLMAccessor_v0_Person retain]: message sent to deallocated instance 0x60800016ba00
I debugged all the data source methods of the NSOutlineView when tapping the arrow to expand the row, but no method is called.
Any idea of what’s happening?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 23 (11 by maintainers)
I am having
EXC_BAD_ACCESSwhenexpandItemis called (similar to expand group in UI)When I try to use debugger to
po iteminviewForTableColumndelegate method, it shows as[Deleted Object], but it is the Realm Object if I log it usingdump(item)My solution to this, is copying the array, and call
expandItemas late as possible (in my case viewDidAppear)Hope this provides an idea about the issue.
i ran into the same issue and ended up solving it in a similar way as @lm2s—however this doesn’t seem like a very performant solution.
are there any examples of using realm properly with NSOutlineView?
For future reference of anyone having this problem, like I did.
Instead of using the RLMResults array directly in
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item.Copy the objects into a NSArray to make sure that they are not released and then use the NSArray.
Using the above code as an example:
NSArray *objectsArrayRLMResults *array.RLMResults arrayinto theobjectsArray.objectsArrayinstead ofarray