Goal
Use NSPasteboard's canReadObjectForClasses:options:
within a custom toolbar item's - (void)validate
to determine the toolbar's enabled state.
Issue
When using NSPasteboard pasteboardWithName
and then calling canReadObjectForClasses:options:
within the toolbar item's - (void)validate
method it causes the Leak Profiler to detect leaks.
Stack Trace of detected leak
0 libsystem_malloc.dylib _malloc_zone_calloc
1 Foundation -[NSConcreteMapTable initWithKeyOptions:valueOptions:capacity:]
2 AppKit -[_NSPasteboardTypeCache init]
3 AppKit -[NSPasteboard _updateTypeCacheIfNeeded]
4 AppKit -[NSPasteboard _cachedTypeNameUnion]
5 AppKit -[NSPasteboard(NSTypeConversion) _conformingTypes]
6 AppKit -[NSPasteboard canReadObjectForClasses:options:]
7 testingPasteboardLeak -[TestToolbarItem validate] ~/Documents/Code/tests/testingPasteboardLeak/testingPasteboardLeak/TestToolbarItem.m:14
8 AppKit -[NSToolbarItemViewer configureForLayoutInDisplayMode:andSizeMode:inToolbarView:]
9 AppKit -[NSToolbarView _layoutDirtyItemViewersAndTileToolbar]
10 AppKit -[NSToolbarView _syncItemSetAndUpdateItemViewersWithSEL:setNeedsModeConfiguration:sizeToFit:setNeedsDisplay:updateKeyLoop:]
11 AppKit -[NSToolbarView _noteToolbarLayoutChanged]
12 AppKit -[NSView _setWindow:]
13 AppKit -[NSView addSubview:]
14 AppKit -[NSThemeFrame addTitlebarSubview:]
15 AppKit -[NSThemeFrame _showHideToolbar:resizeWindow:animate:]
16 AppKit -[NSWindow _showToolbar:animate:]
17 AppKit -[NSToolbar _show:animate:]
18 CoreFoundation -[NSSet makeObjectsPerformSelector:]
19 AppKit -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:]
20 AppKit -[NSNib _instantiateNibWithExternalNameTable:options:]
21 AppKit -[NSNib _instantiateWithOwner:options:topLevelObjects:]
22 AppKit -[NSStoryboard _instantiateControllerWithIdentifier:creator:storyboardSegueTemplate:sender:]
23 AppKit NSApplicationMain
24 libdyld.dylib start
Example Code
Custom Toolbar item's validate method:
- (void)validate {
NSPasteboard *myPasteboard = [NSPasteboard pasteboardWithName:@"TestPasteboardName"];
BOOL isValid = [myPasteboard canReadObjectForClasses:@[[NSString class], [NSURL class]] options:nil];
}
WindowController which is a delegate to the toolbar:
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)aToolbar {
return @[@"test"];
}
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)aToolbar {
return @[@"test"];
}
- (nullable NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
TestToolbarItem *item = [[TestToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[item setTitle:@"TestToolbar"];
return item;
}
What I've tried so far
- Use NSPasteboard releaseGlobally when closing the window -- leak still present.
- Wrap the pasteboard check in
@autoreleasepool
-- leak still present. - Using
releaseGlobally
directly after the pasteboard check gets rid of the leak, but obviously also clears out the pasteboard.
So is there a way to use a private pasteboard's canReadObjectForClasses:options:
within a custom toolbar item's validate method without causing a leak?