Cocoa forControlEvents:WHATGOESHERE - cocoa

In Cocoa/Objective-C if I have created a button programmatically, what do I put in for my control event?
[btnMakeChar addTarget:self action:#selector(makeChar:) forControlEvents:WHAT GOES HERE?];
In iOS you can write it like so forControlEvents: UIControlEventTouchUpInside
I can't find anything to show what I would use for just cocoa, not cocoa touch

I'm not sure if I understand you correctly, but if you're programming a Mac,
[theHappyButton setTarget:self];
[theHappyButton setAction:#selector(doStuff)];
it is two separate lines, rather than the one combined line of code on an iPhone.
I hope that is what you were after??
To find it in the doco: choose on the 10.6 doco (not iOS) and search on "setAction:". You'll see it in NSControl Class Reference. NSButton is of course a subclass of NSControl.

The method you're asking about does not exist in Cocoa, so nothing goes there. Cocoa controls have a single target with a single action, and either use a different addTarget:-type method for each kind of action or expect a delegate object that will handle all the events they generate.

Related

How can I hook up NSWindow's initialFirstResponder when using Storyboards in InterfaceBuilder?

I'm frustrated with the wall that using storyboards seems to put between NSWindows/NSWindowControllers and NSViews/NSViewControllers. A specific example: What good is the initialFirstResponder outlet on NSWindow if the whole view hierarchy is in a separate scene and can't be referenced?
I'd like to make the window called "progred"'s initialFirstResponder the "Content View" view from the View Controller Scene, but you can't make IBOutlet references across scenes. I'd be perfectly happy to put the ViewController and the Window in the same scene, but I can't seem to get that to work with all of the dragging/dropping I've tried to do from one scene to another, or even trying to add a new one from the toolbox. It seems that you're required to use a segue relationship to assign a NSViewController to a NSWindow.
I've googled but I'm not finding anything on this problem which might just mean I'm missing something obvious as I'm pretty new to Storyboards as I can't imagine I'm the first to notice this :).
I've been going through just this in swift (Xcode 6.3.1). IB appears to be unable to do what we want despite all the doco and advice saying "control drag....". My (eventual) solution/workaround was to set it in code, in viewWillAppear, of the view controller. I'd tried a variety of approaches until I encounter some apple doco that declared that the initialFirstResponder must be set BEFORE the window displayed. Hope this helps.
By the way, watch out for the default Window behaviour being "restorable" which seems to restart the (rebuilt) app with the focus in the last field the app was killed in....sigh

How does one display a new view controller in the same Mac window?

I'm fairly new to Mac development and am slightly confused by the new "storyboard" feature in Xcode 6. What I'm trying to do is segue from one view controller to another in the same window. As of right now, all the different NSViewControllerSegues present the view controller in a new window, be it a modal or just another window. What I'd like to do is just segue within the same window, much in the same way one would on iOS (though an animated transition is not crucial). How would this be achieved?
If you provide a custom segue (subclass of NSStoryboardSegue) you can get the result you are after. There are a few gotchas with this approach though:
the custom segue will use presentViewController:animator so you will need to provide an animator object
because the presented view is not backed by a separate Window object, you may need to provide it with a custom NSView just to catch out mouse events that you don't want to propagate to the underlying NSViewController's view
there's also a Swift-only glitch regarding the custom segue's identifier property you need to watch out for.
As there doesn't seem to be much documentation about this I have made a small demo project with custom segue examples in Swift and Objective-C.
I also have provided some more detail in answer to this question.
(Reviving this as it comes up as first relevant result on Google and I had the same problem but decided against a custom segue)
While custom segues work (at least, the code given in foundry's answer worked under Swift 3; it needs updating for Swift 4), the sheer amount of work involved in writing a custom animator suggests to me that their main use case is custom animations.
The simple solution to changing the content of a window is to create an NSWindowController for your window, and to set its contentViewController to the desired viewController. This is particularly useful if you are following the typical pattern of storyboards and instantiate a new ViewController instance every time you switch.
However.
The NSStoryboard documentation says, quite clearly in macOS, containment (rather than transition) is the more common notion for storyboards which led me to look again at the available tools.
You could use a container view for this task, which adds a NWViewController layer instead of the NSWindowController outlined above. The solution I've gone with is to use an NSTabViewController. In the attributes inspector, set the style to 'unspecified', then select the TabView and set its style to 'tabless'.
To change tabs programatically, you set the selectedTabViewItemIndexof your TabViewController.
This solution reuses the same instance of the ViewControllers for the tab content, so that any data entered in text fields is preserved when the user switches to the other 'tab'.
Simple way with no segues involved to replace the current view controller in the same window:
if let myViewController = self.storyboard?.instantiateController(withIdentifier: "MyViewController") as? MyViewController {
self.view.window?.contentViewController = myViewController
}

What is a standard way to add a ViewController in a Mac OS X Cocoa app? (or is it required?)

I'd like to start a Cocoa app with a ViewController just like the iOS "Single View App" template, but there is no such template (is there a public / open source one that can be used?)
Is it true that for Cocoa apps, we don't really need one, because an NSView can do everything already? We can just put all the event handling in our custom NSView class. Could it be that iOS requires it a lot more because rotation is handled by the ViewController and rotation is usually required? But if we use MVC, then it might be better to always use a ViewController, and if so, is there a standard way, a template, to do it?
The "Controller" in OS X with respect to managing NSViews is the NSWindowController. Though Drummer says that NSViewController isn't very useful, I must disagree - it is useful for splitting up your NSWindowController once it gets too large, and has clear logical divisions in terms of views.
You could have one NSWindowController, and once it gets complicated enough, the NSWindowController could delegate tasks corresponding to specific views to subclasses of NSViewController, and in that respect it is very useful.
In the default templates (if I remember correctly) the AppDelegate takes the role of the window controller, though it isn't technically one. In more complex applications it is a good idea to instantiate a window controller instead.
As long as you don't mix up the controller and view anything can be used. The View should be relegated to just display and basic input handling.
On OS X NSViewController isn't as often used as UIViewController on iOS. One of the reasons is that it's not really useful and lacks a lot of the nice features of UIViewController. There are only a couple of situations where you really have to use them, like when using an NSPopover.
There are several ways to structure your OS X code. One of them is using NSWindowController. You can think of NSWindowController as the equivalent of UIViewController on iOS.

Creating gradient button bar in cocoa

My question is almost exactly the same as this question, however the answer accepted (and only) answer was to use BWToolkit which is no longer an option for me because it isn't compatible with Xcode 4.
How can I create a similar bar in interface builder or programmatically, without BWToolkit?
You can look at the source code of BWToolkit. It uses a custom NSView subclass to do the drawing. Cocoa hasn't got a built-in control for this.
Alternatively, you can use BWToolkit, but just the parts you need (BWAnchoredButtonBar, BWSplitView, BWAnchoredButtonBar and the NSColor and NSView categories). You don't need to include the entire framework in your app.

resetting the image in an NSView

I think this is a very simple question, but I’m new to programming so I may be going about it in a wrong-headed way.
I have a basic understanding of Objective-C writing terminal applications and am teaching myself how to use the Cocoa GUI.
I understand how to use IBOutlet and IBAction to connect a simple button to a method that will repeatedly send random numbers to a textfield.
I understand how to add a NSView file, connect it to a custom view in interface builder and draw a path through random points in the view when the application launches.
(I’ve been putting this code inside the - (void)drawRect:(NSRect)dirtyRect method that is declared when the file is created).
What I can’t seem to figure out is how to connect a button to an action that will then ‘refresh’ the view – in this case repopulate it with another set of random points connected with a path. Looking at the documentation, I think I should somehow be using
– (void) setNeedsDisplay(BOOL)flag
but nothing I have tried so far had worked. Please tell me, what am I missing here?
Something like this:
- (IBAction)refreshButtonAction:(id)sender
{
[theView setNeedsDisplay:YES];
}
Connect your button to that action. "theView" is a reference to your custom NSView.

Resources