Reputation: 43
I have an app that uses multiple Modal Sheets for data entry. The methods in opening the modal sheets worked fine, and still work fine, but they have been deprecated and I fear they will soon not work with future releases of Xcode. Here, Apple points out how to use modal sheets,
- (void)showCustomSheet: (NSWindow *)window
// User has asked to see the custom display. Display it.
{
if (!myCustomSheet)
//Check the myCustomSheet instance variable to make sure the custom sheet does not already exist.
[NSBundle loadNibNamed: @"MyCustomSheet" owner: self];
[NSApp beginSheet: myCustomSheet
modalForWindow: window
modalDelegate: self
didEndSelector: @selector(didEndSheet:returnCode:contextInfo:)
contextInfo: nil];
// Sheet is up here.
// Return processing to the event loop
}
but with the release of Xcode 5.1, they identify that the loadNibNamed method has been deprecated and that we should use a similar function referencing top-level objects.
The problem I am having, is changing this:
[NSBundle loadNibNamed:@"OrderDetailsWindow" owner:self];
into this.
NSArray *array;
[[NSBundle mainBundle]loadNibNamed:@"OrderDetailsWindow" owner:self topLevelObjects:&array];
This method call does in fact open the modal sheet. However, at the end of my method that opens the modal sheet, Xcode hangs-up with this error.
0x7fff8c33b097: andl 24(%r11), %r10d Thread1: EXC_BAD_ACCESS (code:EXC_I386_GPFLT)
I'm not sure what this is telling me. It doesn't give me any information in the debug area. Could this have to do with the topLevelObjects array not being released properly? Any thoughts on how to make this work a little more smoothly? Apple's out-of-date library is driving me nuts!
Upvotes: 4
Views: 4126
Reputation: 122391
I always use a NSWindowController
subclass with a custom delegate for my sheets:
From the window that wants to display the sheet:
_myModalController = [[MyModalController alloc] init];
_myModalController.delegate = self;
[_myModalController beginSheet:self.window];
Then within the modal window controller, I have:
- (id)init {
self = [super initWithWindowNibName:@"MyModalWindow" owner:self];
return self;
}
- (void)beginSheet:(NSWindow *)mainWindow {
[NSApp beginSheet:[self window]
modalForWindow:mainWindow
modalDelegate:self
didEndSelector:@selector(_didEndSheet:returnCode:contextInfo:)
contextInfo:nil];
}
- (void)endSheet:(NSWindow *)mainWindow {
[NSApp endSheet:[self window]];
[[self window] orderOut:mainWindow];
}
This appears to avoid the whole issue of loadNibNamed:
becoming deprecated.
Upvotes: 0
Reputation: 3097
Yes, Apple's documentation is a mess. The "Sheet Programming Topics" document has not been updated since 2009.
You don't show the full code after the change but my guess is that your problem is with the memory management of your NIB's objects.
From the documentation of the new loadNibNamed:owner:topLevelObjects:
Unlike legacy methods, the objects adhere to the standard cocoa memory management rules; it is necessary to keep a strong reference to them by using IBOutlets or holding a reference to the array to prevent the nib contents from being deallocated.
Outlets to top-level objects should be strong references to demonstrate ownership and prevent deallocation.
You have the NSArray that holds the top level objects inside your method. Once the execution leaves this method, the NSArray will be derefernced and released and so are all your top level objects if those are not strongly referenced anywhere else.
You need to either connect your top level objects in the NIB to outlets in your Window Controller or keep the NSArray as a member variable of your Window Controller instance, so it doesn't get released once your sheet showing method exits. And make sure that myCustomSheet properly declared and connected from the sheet's NIB.
Also, [NSApp beginSheet:]
is deprecated as well, you now call beginSheet on an instance of NSWindow.
Upvotes: 4