So i have a windowController which i pop up using NSApp this window is called from mainWindowController.
ScriptSettingWindowController *mySettings = [[ScriptSettingWindowController alloc]initWithWindowNibName:#"ScriptSettingWindowController" owner:self];
[NSApp runModalForWindow:[mySettings window]];
There are other UIElements which gets displayed only when using Owner:self. When using owner:self it takes over mainWindowController.
enter image description here
When i close the NSApp The control returns to the mainWindowController. But ends up crashing the application. I believe the control has to be returned back to mainWindowController before closing the NSApp.
To close the modal i use
[NSApp stopModal];
[NSApp orderOut:self];
[NSApp close];
but they do not close the popup.
[[self window] close];
[[self window] close]; this does close the window along with some variables being cleared and crashing the app.
Im dealing with an old project here and have no clue about mac development. Any help would be appreciated. thanks in advance
I am opening an NSWindow as NSSheet and I want to hold the thread until the NSSheet is closed.
_license = [[LicenseArgWindow alloc] initWithWindowNibName:#"LicenseArgWindow"];
[self.window beginSheet:self.license.window completionHandler:^(NSModalResponse returnCode) {}];
[NSApp beginSheet: _license
modalForWindow: _window
modalDelegate: self
didEndSelector: nil
contextInfo: nil];
///here is the problem
///the thread reaches here wheather the nswindow is closed or not
BOOL isAgreed = _license.isAgreed;
How to stop the thread at NSSheet launch and the thread should not pass until the NSWindow is closed
Please help. Many Thanks
Set the didEndSelector parameter in:
[NSApp beginSheet: _license
modalForWindow: _window
modalDelegate: self
didEndSelector: #selector(didEndSheet:returnCode:contextInfo:)
contextInfo: nil];
and have that do the "accepted license" bit:
- (void)didEndSheet:(NSWindow *)sheet
returnCode:(NSInteger)returnCode
contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
BOOL isAgreed = _license.isAgreed;
}
Here is a guide from Apple.
The whole point of sheets is that they are modal for just the one window. The rest of the app has to continue to function. The user can work with other windows or do global actions like open a new file, etc. To block the whole app's execution waiting for the sheet is entirely against the purpose of sheets as a UI mechanism.
If you want an app-modal dialog, run the dialog as a modal window (not sheet). You can either use an NSAlert which has a runModal method, or you can use an arbitrary window using -[NSApplication runModalForWindow:].
I currently have a window open which was opened via:
// FirstWindowController
[self showWindow:self];
[[self window] makeKeyAndOrderFront:self];
[NSApp runModalForWindow:[self window]];
And upon click of a button I'd like to hide FirstWindowController via:
// FirstWindowController
[self.window orderOut:self];
And then show my second window:
// SecondWindowController
[self showWindow:self];
[[self window] makeKeyAndOrderFront:self];
[NSApp runModalForWindow:[self window]];
The first window disappears correctly, and the second window appears. But I can't actually use the NSTextFields in the input. But I can click the cancel button to hide SecondWindowController and give focus back to FirstWindowController.
Why can't I click any of the NSTextField elements?
I had the same problem. It worked when the window had a title bar and otherwise not. It seems like that a window needs to have a title to become a keyWindow.
The workaround for this is to make a subclass of NSWindow and override -canBecomeKeyWindow:
(BOOL)canBecomeKeyWindow {
return YES;
}
The loadFile method starts a NSTimer to load an process a file over time without blocking the application in a while loop. This timer is not firing with the first bit of code, and is with the second bit. The issue is the second bit shows the sheet as a panel style window, not as a sheet.
How do I get a sheet that can still do work?
Show Sheet but no work is done
[self.sheetView loadFile:filename];
[[NSApplication sharedApplication] beginSheet: self.sheetView
modalForWindow: self.window
modalDelegate: self
didEndSelector: nil
contextInfo: nil];
[[NSApplication sharedApplication] runModalForWindow: self.sheetView];
Show window and work is done
NSModalSession session = [NSApp beginModalSessionForWindow:self.sheetView];
NSInteger result = NSRunContinuesResponse;
[self.sheetView loadFile:filename];
// Loop until some result other than continues:
while (result == NSRunContinuesResponse)
{
// Run the window modally until there are no events to process:
result = [NSApp runModalSession:session];
// Give the main loop some time:
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
}
[NSApp endModalSession:session];
Is there a reason why NSThread can't be used? That's the obvious answer ...
In a pet application I'm writing, on the main window, I have a few custom views aligned under each other, each with a label, a combobox and a button.
Clicking the button invokes code that finds the combobox in the same view, and then calls the following function (a class method of RVListEditorController):
+ (void) editComboBox: (NSComboBox *) aComboBox
{
// Analyze says "possible leak", but both methods ending the panel will release the controller.
RVListEditorController *controller = [[RVListEditorController alloc] initWithComboBox: aComboBox];
[NSApp beginSheet: [controller window]
modalForWindow: [aComboBox window]
modalDelegate: controller
didEndSelector: NULL
contextInfo: nil];
}
The code creates an instance of RVListEditorController. That controls a panel that allows me to edit the list in the combobox (remove items, sort items, etc.). It has, among other controls, two buttons that close it, Cancel and OK.
The code for the two buttons is:
- (IBAction) closeSheetWithOK: (id) sender
{
[NSApp endSheet: editingPanel];
[editingPanel orderOut: self];
[comboBoxValues setArray: valuesCopy];
if (comboBoxValues.count > 0)
[editedComboBox setStringValue: [comboBoxValues objectAtIndex: 0]];
[self release];
}
- (IBAction) closeSheetWithCancel: (id) sender
{
[NSApp endSheet: editingPanel];
[editingPanel orderOut: self];
[self release];
}
These are the only two buttons that close the sheet. My question is about the lifetime management of the instance. It is allocated in the class method, but then control is handed to Cocoa again and the class method ends. The only place I could find to release the instance is in the two handlers for the closing buttons. My problem is that beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo: doesn't simply open the sheet and then waits until it closes again, returning a value how it was closed. If that were the case, I could close the instance in the class method, and I would feel better.
My question: Is there perhaps a better way to handle the lifetime of the instance, or is there something in Cocoa that allows me to open a sheet window-modally and then wait for it to close again, so I could release the instance right after that? I can't think of any, but I am a relative newbie, after all.
FWIW, the code works, so there are no errors. I am simply not very happy with the construct that I allocate something in a class method that must then be released in two instance methods of itself.
That looks to me like something which should not be a class method and the problems you are having defining its lifecycle are a warning sign that it is being created without clear ownership.
I am simply not very happy with the construct that I allocate something in a class method that must then be released in two instance methods of itself.
There is a certain logic to that - but I would also claim that a window-modal sheet would more naturally be initiated by an instance method. The window is after all a representation of some object, not just a class.
That didn't answer your more general question about life cycles, though.
I managed to get something that worked to my satisfaction. I provided beginSheet: with a method to be called after the sheet ended, giving controller as the context info. IOW:
[NSApp beginSheet: [controller window]
modalForWindow: [aComboBox window]
modalDelegate: controller
didEndSelector: #selector(sheetDidEnd:returnCode:contextInfo)
contextInfo: (void *)controller];
}
The code for the two buttons is now:
- (IBAction) closeSheetWithOK: (id) sender
{
[comboBoxValues setArray: valuesCopy];
if (comboBoxValues.count > 0)
[editedComboBox setStringValue: [comboBoxValues objectAtIndex: 0]];
[NSApp endSheet: editingPanel];
}
- (IBAction) closeSheetWithCancel: (id) sender
{
[NSApp endSheet: editingPanel];
}
and the code for sheetDidEnd:returnCode:contextInfo: is:
- (void) sheetDidEnd: (NSWindow *) sheet returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
{
[sheet orderOut: (id)contextInfo];
[(id)contextInfo release];
}
That is, IMO, the best that can be done for situations like this. The procedure would have been the same if this had been called from an instance method of the window controller, AFAICT.