Get instance of main window controller in app delegate - xcode

I know that, for iOS, you can reference the root view controller from the app delegate like so:
var rootViewController = self.window!.rootViewController
How does one reference the main window controller from the app delegate when targeting OS X? I would like to pass a variable (the managed object context) this way, as I have read that it is a good solution for referencing the moc.

You can access the NSWindowController instance of the main NSWindow like this:
NSApplication.sharedApplication().mainWindow?.windowController

The ! in earlier answers will cause a crash if the window is hidden, so I recommend caching the window either like this or using a computed property:
var mWindow: NSWindow? = nil
func mainWindowCached() -> NSWindow? {
if let window = NSApplication.shared.mainWindow {
self.mWindow = window
}
return self.mWindow
}

You can access like this:
NSApplication.shared().mainWindow?.contentViewController as! YourViewController;

Related

Simple displaying of second window: OS X & Swift

I'm trying to find how to bring up a second view/window after pushing a button on my primary window. I have read about segues and I can get the first window to display the second but the second is not connected to a view controller so I can't add any code to any controls on the second view. Try as I might I cannot create a SecondViewController.swift file and connect it to a window controller or a view controller. The tutorials I have found all deal with iOS and I want OS X which means there are just enough differences to keep me from figuring this out.
Can anyone show me how to do this?
Ta,
A.
First make new file like:
After that, put these codes in your classes and that should do it.
class SecondWindowController: NSWindowController {
convenience init() {
self.init(windowNibName: "SecondWindowController")
}
}
class ViewController: NSViewController {
private var secondWindowController: SecondWindowController?
#IBAction func showSecondWindow(sender: AnyObject) {
if secondWindowController == nil {
secondWindowController = SecondWindowController()
}
secondWindowController?.showWindow(self)
}
}

How do I access the undoManager for my Mac OS app in swift?

I am simply trying to get undo working for the actions a user performs in my app. By default, any text editing the user does has the benefit of undo, but any actions that are done otherwise (from my code) does not.
I can see the documentation explains that I need to get an instance of NSUndoManager and call registerUndoWithTarget, but I am stumped with the first step: getting the undoManager from within my ViewController. Since ViewController is a UIResponder, I tried this:
if let undoManager = self.undoManager {
undoManager.registerUndoWithTarget(self, selector: Selector("removeLatestEntry:"), object: "test")
}
Since that binding returns nil, I thought maybe the ViewController doesn't have the undoManager, so I looked for it in the window:
if let window = NSApplication.sharedApplication().mainWindow {
if let undoManager = window.undoManager {
undoManager.registerUndoWithTarget(self, selector: Selector("removeLatestEntry:"), object: "test")
}
}
Alas, the window binding also returns nil. Sorry, I am very new to this. Can anyone point me in the right direction? Am I supposed to implement my own undoManager or something? There is clearly an undoManager somewhere because anything a user does manually in my textField is getting undo behavior. It seems like this would be a singleton that I could access easily from a ViewController.
--
Edit: BTW, the code above was placed in viewDidLoad and removeLatestEntry is just a function in my ViewController that takes a string and prints it at this point.
To use undoManager, the ViewController needs to be first responder. So:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
becomeFirstResponder()
}
Then, from wherever your action is defined that needs to be reversed, you register your undo and pass it whatever it needs to undo that action. So in my case:
func addEntry(activity: String) {
// some other stuff…
undoManager!.registerUndoWithTarget(self, selector: Selector("removeLatestEntry:"), object: activity)
}

How do you re-open a closed window created in the storyboard in OS X

My question is essential this question, but the answer doesn't seem to work with Swift/Storyboards.
Cocoa: programmatically show the main window after closing it with X
Basically, I have a more or less default application with a menu, a window, and a ViewController. If the user closes the window while the application is running, how do I reopen it?
I have created an action in the app delegate the connects to the "Open" Menu Item. Within this function, I would like to ensure that the window is visible. So if the user has closed it, it should reappear. But I cannot figure out how to access the closed window. Storyboard does not seem to allow me to create an outlet for my Window in my app delegate.
This is quite simple to archive, even it is not an elegant solution. Add a new property to your app delegate for your main window controller. In the following example, I call the controller MainWindowController.
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var mainWindowController: MainWindowController? = nil
func applicationShouldHandleReopen(sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
mainWindowController?.window?.makeKeyAndOrderFront(self)
return false
}
}
In the initialisation of the main window controller I register the controller in the app delegate:
class MainWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
// ...initialisation...
// Register the controller in the app delegate
let appDelegate = NSApp.delegate as! AppDelegate
appDelegate.mainWindowController = self
}
}
That is all, works perfectly for me.

Use NSToolBar Outlet xcode 6 and Storyboard?

I am trying to add an outlet into my viewcontroller for a toolbar item in my window controller. I have tried playing around with first responder and bindings but have not been able to find any solutions.
A similar question that was answered provided some insight but no one has mentioned anything about IBOutlets other than still asking how to add them in the comments. The answer has been accepted so i am assuming no one will add to it.
How to use NSToolBar in Xcode 6 and Storyboard?
Incase my question is unclear at all, i would like to be able to add this to my storyboard program
#IBOutlet weak var Mytoolbar: NSToolbarItem!
func enabletoolbar()
{
Mytoolbar.action = "FunctionIn.ViewController.swift"
Mytoolbar.enabled = true
}
I found a decent workaround by adding IBOutlets to my custom NSWindow class and using the storyboard to connect my views to the IBOutlets. Then, I accessed these views from my NSViewController class by getting them from the custom NSWindow.
Basically you need to set the action and other properties to the toolbaritem but not in the toolbar. So try the same.
i ended up doing this in my view controller which seems to work
override func viewDidLayout() {
var x = self.view.window?.toolbar?.items[1].label
println(x)
if(self.view.window?.toolbar?.items[0].label! != "Check")
{
toobarediting()
}
println("didlay")
}
func toobarediting() {
self.view.window?.toolbar?.insertItemWithItemIdentifier("Check", atIndex: 0)
}
func toolbarcheck(functiontoset: Selector) {
var y = self.view.window?.toolbar?.items[0] as NSToolbarItem
y.action = functiontoset
if(functiontoset != nil)
{
y.enabled = true
}
}
It seems to allow me to make the tool bar button clickable/unclickable when ever i require it to change it just seems so much more bulky and error prone than
myitem.enable = fale
myitem.action = nil
is this really the best way for a storyboard based application in osx?
While connectiong IBActions works by using either the First Responder or by adding an "Object" to the scene, then changing its class to the window's view controller class, this doesn't help with IBOutlets and delegates that you'd like to point to the view controller.
Here's a work-around for that:
Add the Toolbar to the View Controller, not to its Window. That way, you can make all the IBOutlet connections in the View Controller Scene easily. I've done that for years and found no issues with it, even when using Tabs.
You'll have to assign the window's toolbar in code, then. E.g. like this:
#interface ViewController ()
#property (weak) IBOutlet NSToolbar *toolbar; // connect this in your storyboard to the Toolbar that you moved to the View Controller Scene
#end
- (void)viewWillAppear {
[super viewWillAppear];
self.view.window.toolbar = self.toolbar;
}

How to control instance in another view controller

I'm new to Swift and OS X programming.
I am creating a desktop application with two view controllers, which are in a split view controller. How can I get access to the instances in another controller and change its attributes?
An example:
We have a drawing application, one view is canvas, the other is tools. There is a 'clear' button in tool view, how to set the canvas clear when click on this button?
You can try to use singleton pattern in your code. When you create the view controller, put the var out of the class like:
var fooViewController = FooViewController(...)
class FooViewController{
...
}
Then you can use the fooViewController anywhere in your project.
If you are working with storyboard, you can try some code like this:
var story = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
var view:MainTabViewController = story.instantiateViewControllerWithIdentifier("MainTab") as MainTabViewController
Hope this can be helpful.
You can use delegates and protocols! Link to Official Apple Documentation
Heres a quick example:
protocol toolsProtocol {
func pressedClear()
}
var delegate : toolsProtocol
In your canvas class
class Canvas: UIViewController, toolsProtocol {
Tools.delegate = self
func pressedClear() {
// Insert stuff happens here
}
}

Resources