What object a menuitem action triggered segue should be called on? - macos

I have a menuitem selection triggered segue you can see on the attached pictures
The NSMeniItem connections:
The segue it triggers:
How can I trigger the segue programmatically.
It has an identifier, it's ok.
But what object on I have to call the
(void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender;

#vadian pointed me out that I need the windowcontroller the segue should be called on first and I can get it like this
let mainStoryBoard = NSStoryboard(name: "Main", bundle: nil)
windowController = mainStoryBoard.instantiateController(withIdentifier: "Preferences") as! NSWindowController
windowController.showWindow(self)
where
windowController is a property in AppDelegate
"Preferences" is the identifier in the Storyboard
it has benefit of getting a reference to the window controller itself
as I did not need the reference currently just wanted to trigger the segue i stayed with the following solution
[NSApp sendAction:mPreferencesMenuItem.action to:mPreferencesMenuItem.target from:mPreferencesMenuItem];
where mPreferencesMenuItem is the menuitem that triggers the segue

NSViewController and NSWindowController conforms to the NSSeguePerforming protocol. So in your controller subclass you can call [self performSegueWithIdentifier:(NSString *)identifier sender:(id)sender];

Related

Dismiss NSViewController presented with a show segue swift

I have a NSViewController, let's name it SecondViewController (which is called by the previous NSViewController, named FirstViewController, as a modal window with a segue) that calls the other NSViewController, named ThirdViewContoller, with show segue (all segues performed programmatically: self.performSegueWithIdentifier("nameOfSegue", sender: self). When in SecondViewController I write this code:
self.dismissController(SecondViewContoller)
self.performSegueWithIdentifier("startGame", sender: self)
Everything works, but then I need to reopen SecondViewController (with a modal segue) using this code in ThirdViewController:
self.dismissController(ThirdViewController)
self.performSegueWithIdentifier("changeHardness", sender: self)
The ThirdViewController is never dismissed.
BTW, if I try to open ThirdViewController with a modal segue, it crashes, giving that:
2015-03-31 11:24:19.429 MiniGames Ultra[8074:522218] *** Assertion
failure in -[Project.SecondViewController
presentViewController:animator:],
/SourceCache/AppKit/AppKit-1344.72/Controllers/NSViewController.m:803
2015-03-31 11:24:19.429 Project[8074:522218]
presentViewController:animator:: View '''s view is not in a window/view hierarchy. 2015-03-31
11:24:19.431 MiniGames Ultra[8074:522218] (...etc)

ViewController reference in AppDelegate using Storyboard

I am writing a one view application based on storyboard.
I have added a toolbar, clicking on buttons messages are received into the AppDelegate.
I need to forward them to the ViewController but I am not able to get a reference to it in the AppDelegate.
How do I do that?
As simple as that:
- (void)applicationDidBecomeActive:(NSNotification *)aNotification {
if (_viewController==nil) {
_viewController = (ViewController *)[[NSApplication sharedApplication] mainWindow].contentViewController;
}
}

How to hide the initial window on start with OS X storyboards

I am creating an OS X status bar application, so I want the application to start hidden.
I have created a "storyboard" application, and the initial window always shows up, even if "Visible at launch" is unchecked (was unchecked by default).
Note: if I disable "Is initial controller" then the app correctly starts without any window, but my (now orphan) window seems to never be added to the storyboard:
var mainWindow = NSStoryboard(name: "Main", bundle: nil)?.instantiateControllerWithIdentifier("mainWindow")
The "mainWindow" controller is not found (even though I correctly set "Storyboard ID" on the Window Controller).
So I think it's better to leave "Is initial controller" but simply have the main window hidden at the start…
Uncheck the "Is Initial Controller" box on the storyboard, leaving your app without an initial controller. Your app will run, but will have no window.
This might be a bit of a hack, but you can do this
func applicationDidFinishLaunching(notification: NSNotification) {
// Insert code here to initialize your application
NSApplication.sharedApplication().windows.last!.close()
}
And then later on...
NSApplication.sharedApplication().windows.last!.makeKeyAndOrderFront(nil)
NSApplication.sharedApplication().activateIgnoringOtherApps(true)
Uncheck "Is Initial Controller", but then you need to set the storyboard and its associated NSWindowController manually.
The precise way of doing that is shown in this answer, which I'll quote here:
[...] in your AppDelegate, set up a property for the window controller:
#property NSWindowController *myController;
In your applicationDidFinishLaunching: method implementation, create a reference to the Storyboard. This way you get access your window controller from the storyboard. After that, the only thing left to do is to display the window by sending your window controller the showWindow: method.
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize myController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// get a reference to the storyboard
NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:#"Main" bundle:nil];
// instantiate your window controller
myController = [storyBoard instantiateControllerWithIdentifier:#"secondWindowController"];
// show the window
[myController showWindow:self];
}
#end
The way to do this is just like you tried:
let storyboard = NSStoryboard(name: "Main", bundle: nil)
guard let mainWC = storyboard.instantiateControllerWithIdentifier("MainWindowController") as? MainWindowController else {
fatalError("Error getting main window controller")
}
// optionally store the reference here
self.mainWindowController = mainWC
mainWC.window?.makeKeyAndOrderFront(nil) // or use `.showWindow(self)`
The only thing you probably forgot was to uncheck "Release when closed".
This would immediately release the window and prevents the storyboard loading mechanism from finding it even if you had the right identifier.

SWRevealViewController push Segue

I am trying to use a SWrevealViewController for sidemenu . One of the options on it is "User Profile" . Since I access user's profile from various other views , I would like to have to have a push segue to this VC. However , a push segue is not working from SWRevealViewController to UserProfileVC.
Can anyone suggest how I may use a push sugue from SWRevealVC?
Here's my solution:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil]
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"YOUR_VC_STORYBOARD_ID"];
SWRevealViewControllerSeguePushController *segue = [[SWRevealViewControllerSeguePushController alloc] initWithIdentifier:#"ANY_ID" source:self destination:vc];
[segue perform];
Swift version will be
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("LoginRoot") as! UINavigationController
let segue = SWRevealViewControllerSeguePushController.init(identifier: SWSegueRearIdentifier, source: self, destination: vc)
segue.perform()
Navigation controller is UIViewcontroller. i used navigation controller otherwise use UIViewController object.
Create a custom segue from your Reveal View Controller to your side menu view controller using the storyboard editor. Set the identifier as "sw_rear", kind as "Custom" and class as "SWRevealViewControllerSegueSetController".
With this, if you create ordinary "push" segues from your menu view controller to other view controllers they should be pushed normally.

What is a StoryBoard ID and how can I use this?

I am new to IOS developing and recently started in Xcode 4.5. I saw for every viewController that i could set some identity variables including the storyboard ID. What is this, and how can I use it?
I started searching on stackoverflow and couldn't find any explanation for it.
I assumed it's not just some stupid label that I can set to remember my controller right? What does it do?
The storyboard ID is a String field that you can use to create a new ViewController based on that storyboard ViewController. An example use would be from any ViewController:
//Maybe make a button that when clicked calls this method
- (IBAction)buttonPressed:(id)sender
{
MyCustomViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
This will create a MyCustomViewController based on the storyboard ViewController you named "MyViewController" and present it above your current View Controller
And if you are in your app delegate you could use
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
Edit: Swift
#IBAction func buttonPressed(sender: AnyObject) {
let vc = storyboard?.instantiateViewControllerWithIdentifier("MyViewController") as MyCustomViewController
presentViewController(vc, animated: true, completion: nil)
}
Edit for Swift >= 3:
#IBAction func buttonPressed(sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
and
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
To add to Eric's answer and update it for Xcode 8 and Swift 3:
A storyboard ID does exactly what the name implies: it identifies. Just that it identifies a view controller in a storyboard file. It is how the storyboard knows which view controller is which.
Now, don't be confused by the name. A storyboard ID doesn't identify a 'storyboard'. A storyboard, according to Apple's documentation, 'represents the view controllers for all or part of your app’s user interface.' So, when you have something like the picture below, you have a storyboard called Main.storyboard which has two view controllers, each of which could be given a storyboard ID (their ID in the storyboard).
You can use a view controller's storyboard ID to instantiate and return that view controller. You can then go ahead to manipulate and present it however you want. To use Eric's example, say you want to present a view controller with identifier 'MyViewController' when a button is pressed, you would do it this way:
#IBAction func buttonPressed(sender: Any) {
// Here is where we create an instance of our view controller. instantiateViewController(withIdentifier:) will create an instance of the view controller every time it is called. That means you could create another instance when another button is pressed, for example.
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
Please take note of changes in syntax.

Resources