How to Connect Outlets and Actions in Swift/Macos Programaticly

How to connect outlets and actions in Swift / MacOS programaticly

If you want to use storyboard and lay out all your elements there, you can't really avoid the ctrl drag (or just drag if you open the connections inspector on the right).

You could however create your second button programmatically in code and not use the storyboard at all for it. Then programmatically add your constraints too.

You can also add the action of the button programmatically (using addTarget) if you would like but that would require at least the IBOutlet to be setup in order to have a reference to the button.

How to connect a button to a method on Mac OS X

The fundamental difference is that iOS controls can have multiple actions for different events, but Mac OS X controls only have one primary action (in some cases, there are others that can be set up programatically).

When you right-click on a button in a Mac nib, performClick: is under Received Actions; it’s not an event. The only entry under Sent Actions is “selector”, which is the only thing you can connect to an action on another object.

Because there is only one “sent event”, you’ll normally just control-drag/right-drag from the control to the target and select the action rather than control-clicking, selecting the event and dragging from that.

Build UI programmatically for OS X in Swift (without Interface Builder)

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let newWindow = NSWindow(contentRect: NSMakeRect(0, 0, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2), styleMask: NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask, backing: NSBackingStoreType.Buffered, defer: false)
let newText = NSTextField(frame: NSMakeRect(0, NSScreen.mainScreen()!.frame.height/4, NSScreen.mainScreen()!.frame.width/2, 40))
let myView = NSView(frame: NSMakeRect(0, 0, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2))

func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
newText.font = NSFont(name: "Arial Black", size: 24)
newText.backgroundColor = NSColor.clearColor()
newText.bordered = false
newText.textColor = NSColor.whiteColor()
newText.alignment = .CenterTextAlignment
newText.stringValue = "Hello World"
newText.selectable = false
newWindow.opaque = false
newWindow.movableByWindowBackground = true
newWindow.backgroundColor = NSColor(calibratedHue: 0, saturation: 1.0, brightness: 0, alpha: 0.7)
newWindow.title = "Hello World"
newWindow.center()
newWindow.contentView.addSubview(myView)
myView.addSubview(newText)
newWindow.makeKeyAndOrderFront(nil)
}

func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}

Swift macOS SegmentedControl Action not getting called

SOLUTION

let parentViewControllerInstance = self.parent as! ParentViewController
segmentedControl.target = parentViewControllerInstance

In my case I just had to set the delegate as the target of the sendAction method.


Background

Ok, after hours of reading the AppKit Documentation I am now able to answer my own question.

First, debugging the UI showed that the problem was definitely not in the ViewHierarchy.Debugging UI

So I tried to think about the nature of NSButton and NSSegmentedControl. At some point I noticed that both are subclasses of NSControl.

class NSSegmentedControl : NSControl
class NSButton : NSControl

The AppKit Documentation says:

Discussion

Buttons are a standard control used to initiate actions within your app. You can configure buttons with many different visual styles, but the behavior is the same. When clicked, a button calls the action method of its associated target object. (...) You use the action method to perform your app-specific tasks.

The bold text points to the key of the solution – of its associated target object. Typically I define the action of an control item like this:

button.action = #selector(someFunc(_:))

This causes the NSControl instance to call this:

func sendAction(_ action: Selector?, to target: Any?) -> Bool

Parameter Description from the documentation:

Parameters

theAction


The selector to invoke on the target. If the selector is NULL, no message is sent.


theTarget


The target object to receive the message. If the object is nil, the application searches the responder chain for an object capable of handling the message. For more information on dispatching actions, see the class description for NSActionCell.

In conclusion the NSControl instance, which was firing the action method (in my case the NSSegmentedControl), had no target to send its action to. So it was only able to send its action method across the responder chain - which obviously has been nil while the first responder was located in another view.

Programmatically navigate to another view controller/scene

I already found the answer

Swift 4

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "nextView") as! NextViewController
self.present(nextViewController, animated:true, completion:nil)

Swift 3

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)

let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("nextView") as NextViewController
self.presentViewController(nextViewController, animated:true, completion:nil)

How to connect an NSControl to an Action *and* a label in IB?

No this is not possible

Multiaction is not possible for OSX application.

Cant control drag a reference object to the ViewController in Xcode 9.2 (9C40b) iOS project

Launch screens are not able to have outlets attached to them. They are static. If you'd like to have a "launch screen" that you can manipulate, duplicate your launch screen layout into an initial view controller and do what you like there.



Related Topics



Leave a reply



Submit