How do I open another window in macOS in Swift with Cocoa
The Window Programming Guide is a great place to understand how windows are managed in general.
Specifically (assuming you know how to present a window controller scene in storyboards), you need somewhere to store references to the new window controllers so they’re not immediately deallocated (and disappear) when presented.
In your case, you may want to keep an array of your open detail windows in the master window controller, so that if the master goes away, the details do as well. When a detail window is open (a controller instance is created and its window shown), you’ll store its controller in the array; when closed, you remove its controller from the array so it’s deallocated.
There are a number of ways to do this, depending on how much control you want, how you want child window ownership to work, etc., but this basic pattern is usually sufficient.
To instantiate a new window controller scene from a storyboard:
var myWindowController = NSStoryboard(name: "MyStoryboardFileName", bundle: nil)?.instantiateControllerWithIdentifier("MyWindowControllerIdentifier") as MyWindowControllerClass
myWindowController?.showWindow(self)
Adding a second View Controller to storyboard
You are correct that you have to create a NSViewController
subclass for the second view controller. The next step to take is to set the second view controller's class to your subclass. Set the view controller's class using the identity inspector.
After setting the second view controller's class to your subclass, you should be able to create outlets and make connections from user interface elements in the second view controller to that view controller's source code file.
Open NSWindow from xib while using storyboards and swift
In your second nib:
class SecondNibController: NSWindowController {
override var windowNibName: String? {
return "SecondNib" // no extension .xib here
}
}
Remember to connect the window
outlet of SecondNibConntroller
to your window.
In your main storyboard:
class ViewController: NSViewController {
let secondNibController = SecondNibController()
@IBAction func openSecondWindow(sender : AnyObject) {
secondNibController.showWindow(nil)
}
}
OS X storyboards: using show segue without allowing duplicate new windows to show?
Edit: While the answer below does work, it is definitely not the best way. In your storyboard, select the view controller for the destination view then go to the attributes inspector and change Presentation from Multiple to Single. That's it, no code required.
Not sure this is the best way but in the NSViewController
that is pushing the segue, you could add a property for the destination NSViewController
and, in your prepareForSegue:sender:
method, assign the destination view controller. Finally, in the shouldPerformSegueWithIdentifier:sender:
method, check to see if the destination view controller is assigned, and, if so, bring its window to the front and return NO
meaning don't perform the segue, otherwise, return YES
. Here's a quick example (to be included in the NSViewController
with the button to initiate the segue):
@interface ViewController ()
@property (weak) NSViewController *pushedViewController;
@end
@implementation ViewController
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if (self.pushedViewController) {
[self.pushedViewController.view.window makeKeyAndOrderFront:self];
return NO;
}
return YES;
}
- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
self.pushedViewController = segue.destinationController;
}
@end
When you close the window containing the destination view controller, this will set the pushedViewController property of the original view controller to nil so the segue will perform if the window is not already opened. Again, there may be a better way to do this. Hope this helps.
Jon
How to make two windows pop out in the beginning on a Swift 4 Cocoa application?
You have to get a reference to the window controller in your storyboard from the second window you want to show. Add this code to your NSApplicationDelegate
in applicationDidFinishLaunching
. Don't forget to set the identifier from the WindowController in the Storyboard
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let windowController = storyboard.instantiateController(withIdentifier: "MyWindowController") as! NSWindowController
windowController.showWindow(self)
Related Topics
Referencing Self in Super.Init
Images Inaccessible from Asset Catalog in a Swiftui Framework
Swiftui: How to Set Position of Scrollview to Top Left? (Both Scrolls Is Enabled)
Why I Can Not Use Equatable Function in My View When the View Can Use It in Swiftui
Cannot Invoke Initializer for Type 'Sqlite3_Destructor_Type'
How to Combine Two Nsdictionary in Swift
Count the Number of Lines in a Swift String
How to Tell If a Symbolic Link Exists at a Certain Path
Error: Extraneous Argument Label 'No1:' in Call
Why Use Float(Arc4Random())/0Xffffffff Instead of Drand()
Chain Network Calls Sequentially in Combine
Generics and Functional Programming in Swift
Perform Migration by Adding List() and Another Model Class
Setting Medium and Long Measurement Symbols in Swift 3
Swift 5 Coredata Predicate Using Uuid
Diffrence Between Function and Generic Function in Swift
Why Does Realm Use Realmoptional<Int> Rather Than Int? for Optional Properties