I have an app that uses a NSOpenPanel so that the user can select multiple files for import and also has a typical preferences panel. The prefs panel is stored in the .xib
file.
A problem occurs after the user has called up the preferences panel. Until then the NSOpenPanel works absolutely fine, all logic is executed in the completion block and it can be re-called again and again. However, once the user sellects the Preferences option and dismisses that sheet then every subsequent call to -(IBAction)addFiles:
causes an exception:
They’re declared like this:
@interface BQSAppDelegate
{
NSOpenPanel *addFilesPanel;
}
@property(assign)IBOutlet NSPanel*prefs_panel; //connected to a NSPanel in the .xib
And used:
@implementation BQSAppDelegate
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// other initialisations not to do with addFilesPanel….
addFilesPanel = [NSOpenPanel openPanel];
addFilesPanel.canChooseDirectories = YES;
addFilesPanel.allowsMultipleSelection = YES;
}
-(IBAction)addFiles:(id)sender //button on main window pressed
{
[addFilesPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if (addFilesPanel.URLs.count < 1 || result != NSFileHandlingPanelOKButton) {
NSLog(@“User cancelled”);
[addFilesPanel orderOut:self]; //I’ve tried it without this line with exactly the same results
}
else {
//do things…
}
}];
}
-(IBAction)preferences:(id)sender //bound to the usual Apple+’,” shortcut and app menu item
{
if (self.prefs_panel.isVisible) {
return;
}
[self.window beginSheet:self.prefs_panel completionHandler:^(NSModalResponse returnCode) {
NSLog(@"completed"); //is never executed...
}];
}
-(IBAction)ok_prefs:(id)sender //called when the user presses a button on the Preference panel
{
[self.prefs_panel orderOut:self];
}
The exception is:
2015-03-18 20:35:29.913 QS[3634:241869] *** Assertion failure in void associateSheetWithHost(NSWindow *, NSWindow *)(), /SourceCache/ViewBridge/ViewBridge-103/ViewBridgeUtilities.m:83
2015-03-18 20:35:29.914 QS[3634:241869] sheet <NSVBOpenPanel: 0x1003504f0> already has a host <NSWindow: 0x6000001e5e00>
2015-03-18 20:35:29.917 QS[3634:241869] (
0 CoreFoundation 0x00007fff95e7366c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8db6776e objc_exception_throw + 43
2 CoreFoundation 0x00007fff95e7344a +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff9399e471 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 169
4 ViewBridge 0x00007fff8c931333 -[NSWindow(ViewBridgeNeedsSPI) _setSheetHost:] + 305
5 AppKit 0x00007fff8b367a2f -[NSVBSavePanel beginSheetModalForWindow:completionHandler:] + 69
6 QS 0x0000000100017684 -[BQSAppDelegate addFolders:] + 212
7 libsystem_trace.dylib 0x00007fff8be72cd7 _os_activity_initiate + 75
8 AppKit 0x00007fff8acd8b71 -[NSApplication sendAction:to:from:] + 452
9 AppKit 0x00007fff8acd8970 -[NSControl sendAction:to:] + 86
10 AppKit 0x00007fff8aeae86c __26-[NSCell _sendActionFrom:]_block_invoke + 131
11 libsystem_trace.dylib 0x00007fff8be72cd7 _os_activity_initiate + 75
12 AppKit 0x00007fff8ad21509 -[NSCell _sendActionFrom:] + 144
13 libsystem_trace.dylib 0x00007fff8be72cd7 _os_activity_initiate + 75
14 AppKit 0x00007fff8ad3c085 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2775
15 AppKit 0x00007fff8ad3b2b9 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 491
16 AppKit 0x00007fff8ad3a899 -[NSControl mouseDown:] + 714
17 AppKit 0x00007fff8b238a18 -[NSWindow _reallySendEvent:] + 12721
18 AppKit 0x00007fff8acbf16e -[NSWindow sendEvent:] + 446
19 AppKit 0x00007fff8ac71451 -[NSApplication sendEvent:] + 4183
20 AppKit 0x00007fff8aafd608 -[NSApplication run] + 711
21 AppKit 0x00007fff8aae8a14 NSApplicationMain + 1832
22 QS 0x0000000100001fe2 main + 34
23 libdyld.dylib 0x00007fff90d485c9 start + 1
It must be something to do with the way I’m calling and/or dismissing the NSPanel but I don’t know what. I’d really appreciate some help.
It's a cryptic error message, and I'm not sure I understand it's wording despite the comment that solved the problem. I was thinking it had to do with there being a modal run loop associated with sheets, and it may have to do with that-- perhaps there's all the overhead of a modal session still kicking arround, alive somewhere, unless you call endSheet
.
The hint was from this related question about the completion handler not being invoked. The second, unaccepted answer there does seem to indicate that you have to kill the modal session, not just kill the sheet.