Open URL on Menu Item Click - swift

I need to Open a URL when the user clicks on a Menu Item.
Currently I'm using the following code
url = URL(string: "https://www.example.com/test")
NSWorkspace.shared().open(url)
This works fine from a Button.But I cannot connect a Segue from the Menu Item to the view controller inorder to setup an IOAction,so that I can write the necessary code.
How can I solve this problem? Please advice.

Segues are for opening new views or windows from your app. You should implement your function as ordinary #IBAction in your view controller or app delegate, and connect action under Sent Actions in the Connections Inspector with the First Responder in the storyboard scene. You will find your action method there. Cocoa touch will automatically enable or disable the menu item weather the view controller is in the responder chain. If you implement the action method in the app delegate the menu item should always be enabled, because the delegate is always in the responder chain.
#IBAction func openURL(_ sender: AnyObject) {
let url = URL(string: "https://www.example.com/test")
NSWorkspace.shared().open(url)
}

Implement the method as IBAction in the view controller.
Connect the NSMenuItem to First Responder (red cube) of the Application Scene and select the method.
If there are multiple implementations of the method the framework executes the first in the responder chain.

Related

Capture Storyboard Segue from application menu

Is there a way to capture a segue generated from the menu in Application Scene? My searches have not been forthcoming.
I have a Preferences menu item that is under the App name like most other Apple macOS applications, but unlike other segues, that segue is not firing the prepare or shouldPerformSegue methods.
I want to trap the segue like I do with other segues when they fire the above mentioned methods.
A reliable way is:
Connect the segue from the main view controller to the Preferences controller.
In the main view controller create an IBAction. In the action call performSegue
Connect the menu item to the First Responder of the application scene (red cube). Select the IBAction.

Segue from SKScene and back again cause game to "freeze"

I'm developing a SpriteKit game with two different scenes (MainMenu.sks and Settings.sks). I also have a UIViewController.
From the MainMenu the user can tap "Settings" which causes the app to load the Settings.sks scene and present it.
It's done using this code:
// Move to Settings.sks
let transition = SKTransition.flipVertical(withDuration: 1.0)
let loadScene = SettingsScene(fileNamed: "SettingsScene")
loadScene?.scaleMode = self.scaleMode
self.view?.presentScene(loadScene!, transition: transition)
From the Settings.sks scene the user can tap on the SKLabelNode "Change username" which causes the app to load the UIViewController by performing a segue.
The UIViewController contains a UITextField and a UIButton. The UIButton takes the user back to MainMenu.sks.
However, when I'm doing so the it's like a new scene of MainMenu is placed upon the other causing the app to sort of "freeze" and not responding to any touch gestures. I can see from the nodeCount that the nodes are doubled.
A workaround is loading the UIViewController directly from the MainMenu.sks (also via a segue). By doing so, the app works just fine.
I'm suspecting the problem to be the way I load Settings.sks.
What am I missing? Maybe unloading the entire SKView before exiting?
Performing a segue will present a new view on top of the stack. By using a segue to return to the main menu, the app will create a new main menu on top of the UIViewController. I can't say for certain why your app freezes. But I would guess that there are some properties or functions that don't work properly when a new main menu is created and presented from your UIViewController.
I recommend unwinding the segue used to reach the UIViewController instead. This way you can return to the previous view and conserve memory.
You'll need to write an IBAction in your destination view, the main menu in this case:
#IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
}
Then ctrl-drag from your button in the UIViewController to the exit icon in storyboard. You should see an option to use the IBAction unwindToMainMenu that you just wrote. This will create an unwind segue.
A complete guide to unwind segues and multiple examples can be found in this answer: What are Unwind segues for and how do you use them?

How to detect a click from an NSToolbarItem inside an NSWindowController?

I have a toolbar on my macOS app, developed in Swift. The toolbarItem is dragable onto the NSWindowController, and I can setup an IABAction function, I just have a print in the function at the moment. And when I click on the button nothing happen the click does not seem to be recognised as an action ?
I had a few more line of code in the function but deleted it and now have just the print("test") line.
#IBAction func exportCsvClicked(_ sender: NSToolbarItem) {
print("test") }
No output observed, so I'd love to get "test" in the console when I click on this button.
Here is a list of the connections associated with the toolbarItem.
I found a way to get around the fact that the IBAction from an NSToolbarItem does not recognise the click on this item:
1/I made a customSegue from the item to the main window controller (it can go anywhere)
2/The prepare for segue function posts a notification to the notification saying that the item has been clicked.
3/The main view controller observes the notification and presents, either has a popup or a sheet (I got two buttons), the view that I have setup in the storyboard (referencing with the storyboardID). I found that you need to pass on all the necessary variable to setup the view from the main view Controller, and that there was issue of code in the viewDidLoad function of the sheet/popup view not running, I am suspecting that they might be different instances.

How to access NSViewController from app delegate?

In my macOS application I have menu items, which are replicated also in main UI. Application is consisted of main window with its delegate and single view along with its view controller. In app delegate I capture menu item click action, then I need to send this event to my view controller in order to take appropriate actions and also update main UI.
Question is how to access my view controller (NSViewController) from app delegate?
If you have window as an IBOutlet you can do
var rootViewController: MyViewController? {
return window!.contentViewController as? MyViewController
}
func sendPressed(_ sender: Any?) {
rootViewController?.sendPressed()
}
If you don‘t have a window variable you can get it through
NSApplication.shared.orderedWindows.first!
Actually you don't need a reference to the controller. There is First Responder
Declare the IBActions
In Interface Builder connect the menu items to the First Responder (red cube) of the target object and choose the appropriate action.
The action will be executed in the first object of the responder chain which implements the action.

Performing segue from custom imageView class?

I create rounded user icons with a custom UIImageView class. I make these image views interaction enabled, so that when a user taps on one of them, it should segue to another view controller.
I can successfully get each users data printed upon tapping an icon, but I keep getting error "no segue with identifier 'confirm'", even tho I have triple checked that that is the correct identifier. Can one not segue this way?
Here is the code to run when an icon is tapped (this is located inside the icon.swift file) I create an instance of the controller to access the segue on tap:
#objc func iconWasTapped() {
//
var controller = ConfirmOpponentController()
print("\(game.playerOne?.username ?? "") VS \(game.playerTwo?.username ?? "")")
controller.segue()
}
Here is the segue method inside the view controller file:
let SEGUE_TO_CONFIRM = "confirm"
func segue() {
self.performSegue(withIdentifier: SEGUE_TO_CONFIRM, sender: nil)
}
Inside the storyboard, I have controlled dragged and created a push segue, and named it 'confirm'. I did NOT control drag from a button, or an icon. I just linked up the view controllers.
I think in easy way you can Add a tap gesture recognizer to the image view, set the action to be a segue going to your destination view controller, add an if statement to your "prepareForSegue" function.