Modal sheet is not attached to window - macos

I'm trying to call modal sheet inside my root window. I've have success with showing sheet but it is not attached to main window.
I've read about similar problem:
Window outlet is set (it is automaticly set by XCode)
Visible at launch option is unchecked.
My application has storyboard (image below), I'm calling sheet from Root Window Controller. I've tried to call sheet from Root Split View Controller but had no success.
let loginWindow = LoginWindowController(windowNibName: "LoginWindowController")
self.window?.beginSheet(loginWindow.window!, completionHandler: { (res) -> Void in
print("completed")
})

I've tried to call beginSheet (also to display sheet you can use presentViewControllerAsSheet or performSegueWithIdentifier) within viewDidLoad method. That was the error.
You can call sheet only after view was appeared. Then sheet will be placed correctly, inside window and without window/view hierarchy errors.
Now I'm calling sheet in viewDidAppear method and everything is working

Related

How do I set the initial first responder per view in a cocoa app that switches between different views?

My Cocoa App uses one ViewController. I do not use the InterfaceBuilder On app launch a view will be created and the user can do stuff. When clicking a specific button the VC (as the view's delegate) receives a message and then replaces the view with another.
In this new view I want a specific UI element to be the first responder. So far I have not been successful.
The new view has a reference to the desired element (a subview), so the VC can pass it to the window's makeFirstResponder(:_) method.
I tried to do that in the following places:
at the end of the view's init
in the view controller's viewWillAppear()
in the VCs viewDidAppear()
in the latter two I tried:
if let myView = self.view as? MyView {
... here I try to set the UI element as firstResponder ...
}
But in any case I get the following Message:
[General] ERROR: Setting <NSTableView: 0x7f8c1f840600> as the first responder for window <NSWindow: 0x7f8c1ef0efc0>, but it is in a different window ((null))! This would eventually crash when the view is freed. The first responder will be set to nil.
So it appears that at the time I try to set the firstResponder the new view has not yet been attached to the window.
What I also tried is to override the MyView's becomeFirstResponder()method, assuming that when the view is finally presented in the window it will receive that command, but unfortunately this method does not get called.
Is there an easy way to specify an entry point for the responder chain / key view loop per view?

NSWindowController/NSViewController "Presentation" setting in Storyboard

What exactly does the Presentation option(in Attribute Inspector) do in StoryBoard for Cocoa.
It gives two options to select from
Single
Multiple
P.S When googled the title, results are related to powerpoint presentation
The presentation style affects "Show" segues. Possibly it affects other segues too, but I only tested a Show segue. I tested on OS X 10.10.5 (Yosemite) with Xcode 7.1.1.
If a window controller's presentation style is "Multiple" (the default), then a Show segue to the window controller always loads a new instance of the window controller from the storyboard. This means that you can end up with multiple instances of the window controller at once, each with its own window on the screen. By default those windows will stack on top of each other, so it won't be obvious what happened until you move or close one.
If a window controller's presentation style is "Single", and an instance of the window controller has already been loaded from the storyboard, and that window controller still exists (presumably because its window is still on screen), then a Show segue to that view controller will not create a new instance. Instead, the Show segue will bring the existing window controller's window to the front.
This behavior is useful if you want behavior like, say, Xcode's Devices window, where there can only be one such window. You create a "Devices" menu item in the Window menu in your storyboard, and connect it to the Devices window controller in the storyboard with a Show segue. Set the Devices window controller's presentation style to Single. Now the menu item will never create a second Devices window controller if one already exists.
You'll probably want to somehow set the window's excludedFromWindowsMenu property to true, so it doesn't appear twice in the Window menu (because by default it appends itself to that menu). You could, for example, use a subclass of NSWindowController that sets it:
class DevicesWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
window?.excludedFromWindowsMenu = true
}
}
View controllers also have a presentation style, because you can also connect Show segues to view controllers. A Show segue connected to a view controller automatically creates a window controller to contain the view controller at runtime. The window controller's presentation style is effectively set to the view controller's, so you get the same singleton behavior if you set the view controller's presentation to Single.
As far as I can tell, the storyboard setting has no corresponding public property or method you can use in code.
If you connect the Show segue to a storyboard reference (new in Xcode 7), then the segue ignores the presentation style of the destination window controller, and acts as if it were "Multiple". This happens even if the destination is actually in the same storyboard as the reference.

Dynamically changed views in a full screen window in Xamain.Mac (monomac)

I am trying to figure out a correct composition of views and subviews in Xamarin.Mac (monomac) application.
There are very little examples of Windows/Background View/Controls UI with Xamarin.Mac out there and those which I found (basically this project is the best documented one when it comes to Window/View composition) suffer from the same problem - its a static binding of a form Window -> Background view (bound in XCode) -> Controls under the View node. What's being displayed as controls on the view isn't dynamically added via C# and not even a separate view inside the background view.
What I need, is to create a Window, that has a background view that will be semitransparent and then have my application dynamically, depending of the app logic, inject different subviews to background view from C# code. I know that one can add a subview to a view in Xamarin.Mac, but when I try it in my case, the subview just isn't being shown:
GoFullscreen is where the window starts to transform:
private void GoFullScreen ()
{
// Set the window level to be above the menu bar
Window.Level = NSWindowLevel.Normal;
var backgroundView = new LeoBreakBackgroundView ();
backgroundView.SetBreakSubview (_currentBreakViewController);
Window.ContentView = backgroundView;
Window.ContentView.EnterFullscreenModeWithOptions (NSScreen.MainScreen, new NSDictionary());
// Show the window
Window.MakeKeyAndOrderFront (this);
}
At the point I call backgroundView.SetBreakSubview (_currentBreakViewController);
which is:
_currentBreakViewController = currentBreakController;
this.AddSubview (_currentBreakViewController.View);
I don't see the _currentBreakViewController.View being added to backgroundView, but the backgroundView is indeed added onto a window that goes fullscreen.
_currentBreakViewController is a NSViewController and LeoBreakBackgroundView you see in the first snippet is just an NSView without a controller.
Anyways, is it possible to control a View's subview dynamically from code in Xamarin.Mac?

Does anyone know what the new Exit icon is used for when editing storyboards using Xcode 4.5?

Right-clicking the Exit icon yields an empty window. Can't Ctrl-drag a connection to any IB elements or corresponding source files. Docs give no love. Doesn't appear in nib files, only storyboards. My assumption is that it's a corollary to segues, but I don't see any new methods to back it up. Anyone?
I had a hard time following the accepted answer so here is more detail.
Given the photo below on view controller C you can "exit" back to any view controller in the segue path.
ViewController A you can write:
- (IBAction)done:(UIStoryboardSegue *)segue {
// Optional place to read data from closing controller
}
ViewController B you can write:
- (IBAction)back:(UIStoryboardSegue *)segue {
// Optional place to read data from closing controller
}
ViewController C you control drag from "back" button to the green exit option and select back:
ViewController C you control drag from "done" button to the green exit option and select done:
Note: Even though the methods are on other view controllers they show up for the ViewController C's exit. Control dragging and selecting a method defines which ViewController to unwind to.
There's a lot of information in the WWDC video "Session 407 - Adopting Storyboards in your App."
Say you have two view controllers linked by a segue. Implement the following exit action on the first view controller:
- (IBAction)done:(UIStoryboardSegue *)segue {
NSLog(#"Popping back to this view controller!");
// reset UI elements etc here
}
Then, on Storyboard scene for the second view controller, Ctrl-drag from a UI element, such as a button, to the exit icon at the bottom of this view controller. The done: action you added to the code of the first controller will appear as an option. Now, activating the button you Ctrl-dragged to the exit icon will pop back to the first view controller and maintain its original state (ie UI elements such as text input supposedly still intact).
As addition to Eric answer here is how it works with swift:
The function you add to the destination controller looks like:
#IBAction func backFromOtherController(segue: UIStoryboardSegue) {
NSLog("I'm back from other controller!")
}

NSWindowController shows new window

I am very new to mac programming. Just started before 3 days.
I am making a sample app in which i have one button in main window
I am using this code to open a new wndowcontroller
ThirdViewController *tvc = [[ThirdViewController alloc] initWithWindowNibName:#"SecondViewController"];
[tvc showWindow:self];
This working fine but when i press button again it will open same window again so after every click i have +1 window on screen.
What i want is if my new window is already on my screen then button can't add same window.
Thanks in advance:)
If that code is being executed whenever the button is clicked then you’re effectively creating a new window controller, loading its window from a nib file, and showing that window as many times as the button is clicked.
The standard approach to prevent this from happening is having an instance variable that is initially nil and assigning it a window controller only once. Subsequently, the instance variable is not nil any longer and you can test that to avoid creating another controller and loading the nib file again.
You could, for example, declare the following instance variable in your application delegate or whatever controller should be responsible for the third window controller:
ThirdViewController *tvc;
and, when the button is clicked:
if (nil == tvc) {
// If tvc is nil then it's the first time this code is being executed
tvc = [[ThirdViewController alloc] initWithWindowNibName:#"SecondViewController"];
}
[tvc showWindow:self];

Resources