Howto identify modalForWindow using NSViewController - objective-c

I have one NSWindow (mainwindow) for my OSX NSApplicationDelegate. The NSWindow also holds several NSView's where the content is set using NSViewControllers. Currently I ran into a problem when I wanted a NSPanel, a sheet, to drop down from the top of one of my NSViews (not from the top of my app). I wanted to use the code:
[NSApp beginSheet:self.loginSheet.window
modalForWindow:self.view.window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
The loginSheet is a subclass of NSWindowController which loads the xib file using:
loginSheet = [[sheetWindowController alloc] initWithWindowNibName:#"loginSheet"];
However, I run this code from my NSViewController and my self.view.window is always nil. My NSView seems otherwise correctly initialized and works fine, but the drop down of the sheet does not work as my modalForwindow (self.view.window) is nil. If I use the code:
[NSApp beginSheet:self.loginSheet.window
modalForWindow:[[NSApplication sharedApplication] mainWindow]
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
it works like a charm. But from all my searching to find an answer to my problem it seems that this working approach is a big no-no since it blocks the entire app from any response. I wanted my sheet to be linked to one of my NSViews' but I dont see how I can do this given that the app only have one NSWindow? Am I not doing something that makes my self.view.window stay nil? Is there a good way for me to find the parent window of custom views? If you have any suggestions for how to solve this problem or can give me a hint on what I am doing wrong that would be greatly appreciated.
Thanks! Cheers, Trond

You should have a look at the "Positioning Sheets" section of "Introduction to Sheets" docs. It explains how to make a sheet appear from somewhere other then under the window's title bar using window:willPositionSheet:usingRect:

Related

Show all NSWindows

Pretty simple idea here, I want to show all the NSWindows in an app. The idea being that there are two windows in the app, one his hidden the other is vissable. I want to show all the windows in the app and then hide one. I can hide the window I want to hide but I cant show the windows because I am unable to obtain a reference to it. is there anyway of getting a list of all the nswindows in the app then iterating through it and hiding them or something similar, I can use [NSApp windows] however trying to use
NSArray *windowArray = [NSApp windows];
[windowArray[0] makeKeyAndOrderFront:self];
[NSApp activateIgnoringOtherApps:YES];
does not work, nor does:
NSArray *windowArray = [NSApp windows];
NSWindow *tempWindow = windowArray[0];
[tempWindow makeKeyAndOrderFront:self];
[NSApp activateIgnoringOtherApps:YES];
any suggestions?
Well in hindsight I've been a bit stupid. I had two seep rate controller objects each running one window. One was hardly doing anything as the view inside it was being handled by a different object so I just removed that one and made the first controller object take care of both windows. Problem solved.

How to show an NSWindow as sheet at specific location

I have a window like this, having 3 subviews, each one of them has button. On click of those- I need to show sheet.
By using this code, sheet comes in centre of the window.
- (IBAction)closeSubWindow:(id)sender{
[NSApp endSheet:self.subWindow];
[self.subWindow orderOut:nil];
}
- (IBAction)showSubWindow:(id)sender {
[NSApp beginSheet:self.subWindow
modalForWindow:self.window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
}
Is there any option or way to show the sheet at specific co-ordinates?
EDIT:
My current implementation is by using NSPopover. Can I make this NSPopover to animate like sheet?
Take a look at the NSWindow delegate method -window:willPositionSheet:usingRect:
A sheet is per definition that what you see. So no, there is no way to place it at a different position. You could create an own implementation, but maybe it is better in your situation not to use a sheet but e.g. an NSPopover. This is availabe since OSX 10.7 and a great means to have a temporary view for displaying/entering values. By using the transient (or semi-transient) style the framework takes care for managing the display (automatically hiding the popover when no longer needed). Of course you can also have an OK button on it to commit changes.
The popover is also kinda modal, just like the sheet, so, functionally they are quite similar, but you have more freedom regarding its position.

NSApp beginSheet creates a sheet very briefly then disappears

[NSApp beginSheet] is used like so:
[NSApp beginSheet:[testSheetController window]
modalForWindow:[NSApp mainWindow]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
Upon execution the sheet appears for a split second, although it is floating and not attached to the window like a sheet normally would, and then disappears. [NSApp mainWindow] is verified to not be nil. No exceptions are produced. Can anyone suggest what might be causing this behaviour?
I'm adding to an existing project and I've been trying to mimic the structure and the creation of other sheet controllers which are working with this window.
These appear to be two distinct problems: Your sheet probably disappears because it is being released to early. Make sure testSheetController is retained as long as the sheet is visible. The brief flickering in a detached state is likely caused by the Visible at launch property you can turn off when editing the NIB/XIB in Xcode/Interface Builder.

NSView (Content View) as firstResponder

I have a Content View that I use in my preferences nib.
I use a method to change the font of a NSTextView in my app.
This Content View has to be set as firstResponder to get messages from my changeTextFont: method, but since it's not a window it doesn't have a firstResponder. As a result, it does not change the text font at all... does anyone have a workaround for this ?
Thanks a bunch guys.
I could make the sample project work without specifying [self window] as first responder. What I did was:
in (void)changeTextFont:(id)sender, I replaced the statement:
[[self window] makeFirstResponder:[self window]];
with lines:
[[NSFontManager sharedFontManager] setAction:#selector(changeMyFont:)];
[[NSFontManager sharedFontManager] setTarget:self]; //-- this seems to be not mandatory, but I mention it because your case could be different
I renamed changeFont: to changeMyFont::
- (void)changeMyFont:(id)sender
{
With these changes, the font is correctly updated in the example content view.
I don't know if it will work for you, because in the end you are trying to use this code in a different context, but I hope that it will. I would suggest you to first try and modify the sample project so that you can get confident with my solution and then move it to your project to check whether it also works there.

Where to put Root Controller?

I'm getting better and better with doing things for the iPhone in xcode, but here I have ran into a dead end.
I'm trying to build an app with two views: the main one and one for settings. I want to be able to switch between the two of them. Since I need every pixel in the main view I have built a switchView class that simply switch between the two views when I press a button (so much smaller than a tabView), which is working fine.
Now I'm a bit deeper in development and want the settings view to be a table view from where I can navigate to the next level of detail. I have done this before, but without the switch view.
My problem is that I get the table view (in settings) to work, but once I try to push my view controller nothing happens. While debugging I can see that it works through the code (eg didSelectRowAtIndexPath is working) but no new view pops up. Neither any error message.
I have the switchView added in my MainWindow.xib and then do a
[window addSubview:switchViewController.view]; in my AppDelegate to load the main view.
Where should I put the root controller for the navigation for the table view? Because I guess that's the problem I have?
Below the code that results in nothing...
ViewsAppDelegate *delegate =[[UIApplication sharedApplication] delegate];
[delegate.settingsNavController pushViewController:settingsDetailViewController animated:YES];
Happy for any suggestions that could lead me to the right track. Spent way too much time to solve this.
I might be misunderstanding what you're after, but let me try...
When you created your project you should have gotten your MainViewController and an AppDelegate both spun up and created for you. From the snippet you've provided it looks to me like your instantiating a new (and possibly second) app delegate from within your MainViewController.
Rather than doing this, I would suggest that you move your NavigationController up one level to the AppDelegate supplied by the SDK. Then in your MainViewController, add the existing AppDelegate as an IBOutlet and tie them all together in IB. Once you've done that, using the navigation controller should go much more smoothly.
For example, my MainWindow.xib has several objects, and I've highlighted the two that I think you're probably concerned with...
http://www.freeimagehosting.net/uploads/f50268da03.png
*Sorry for the link - I can't post images yet.
Then, from my AppDelegate I customize my applicationDidFinishLaunchingWithOptions like so...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navController.viewControllers = [NSArray arrayWithObject:mainMenuController];
// Override point for customization after app launch
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
That keeps the navController up at the highest level (where I think it belongs) and allows you to push and pop views throughout the entire app while keeping that history of what's on the stack.
Hope that helps - I might have completely misunderstood what you were after.
Good Luck!
Bob