BusyApp solution

[code]import Cocoa

class MainWindowController: NSWindowController {

override var windowNibName: String? {
    return "MainWindowController"

//property for NSSlider to hold old and new values
var sliderValue: Double = 0
var oldValue: Double = 0

//Outlets for text-fields, slider, checkbox and radio buttons (showButton and hideButton)
//Notice that hideButton's outlet never gets used because they both have the same action
@IBOutlet weak var upDownText: NSTextField!
@IBOutlet weak var sliderAppearance: NSSlider!
@IBOutlet weak var secretText: NSSecureTextField!
@IBOutlet weak var decodedText: NSTextField!
@IBOutlet weak var showButton: NSButton!
@IBOutlet weak var hideButton: NSButton!
@IBOutlet weak var checkMeBox: NSButton!

//the stringValue in an NSTextField shows while NSSecureTextField does not. The stringValue is however the same.
@IBAction func revealButtonPressed(sender: NSButton) {
    decodedText.stringValue = secretText.stringValue

//radio button hide is tagged as 1 and hides the tickmarks.
@IBAction func changeSliderAppearance(sender: NSButton) {
    if sender.tag == 1 {
        sliderAppearance.numberOfTickMarks = 0
    } else {
        sliderAppearance.numberOfTickMarks = 10

//takes the current slider value and uses the sliderValue property to hold it.
@IBAction func sliderDescription(sender: NSSlider) {
    sliderValue = sender.doubleValue
    upDownText.stringValue = sliderUpOrDown(sliderValue)
    oldValue = sliderValue

//Resets everything to default. Notice NSOnstate for showButton. Because showButton and hideButton have the same action
//you don't have to specify anything for hideButton. I also call changeSliderAppearance action directly.
@IBAction func reset(sender:NSButton) {
    secretText.stringValue = ""
    decodedText.stringValue = ""
    sliderAppearance.doubleValue = 50
    upDownText.stringValue = ""
    showButton.state = NSOnState
    checkMeBox.state = NSOnState

func sliderUpOrDown(value: Double) -> String {
    if value > oldValue {
        return "Moves up!"
    } else if value < oldValue {
        return "Moves Down!"
    } else {
        return "Nothing happens dude!"


Nice use of implicitly unwrapped optionals for the @IBOutlets! (I didn’t remember that the authors used implicitly unwrapped optionals on @IBOutlets at the bottom of p. 93!)

You don’t need to connect an @IBOutlet to a control in order for the control to trigger an @IBAction method, so get rid of it.

I don’t quite follow the advice to get rid of the hide button outlet. Here is my reset function:

func reset() { self.slider.numberOfTickMarks = self.sliderTicks self.hideTicksButton.state = 0 self.showTicksButton.state = 1 self.checkButton.state = 1 self.revealText.stringValue = "" self.secretText.stringValue = "" self.sliderText.stringValue = "" self.slider.integerValue = self.initialSliderPosition self.sliderPosition = self.initialSliderPosition }

If I get ride of my hideTicksButton outlet, I must also remove the line self.hideTicksButton.state = 0. The app still works, but when I run it I get the console message

[quote]2015-07-29 04:10:13.100 BusyBoard[10977:313838] Failed to connect (hideTicksButton) outlet from (BusyBoard.MainWindowController) to (NSButton): missing setter or instance variable[/quote] I always try to eliminate all warnings, so my inclination would be to keep the outlet and leave the code as it was. Am I missing a step? If not, what advantage is there in eliminating the outlet?

For radio buttons, when you set one of the radio buttons in a group of radio buttons to ON, then the other radio buttons in the group are automatically set to OFF, therefore there is no reason to explicitly change the state of both radio buttons: when you set the Show radio button to ON, the Hide radio button will automatically be set to OFF. As a result, you don’t need an IBOutlet to the Hide radio button because you don’t need to explicitly manipulate it.

[quote]The app still works, but when I run it I get the console message:

That’s because you deleted the hideTicksButton variable but you didn’t delete the connection to that variable, which you created in the .xib file. As a result, when Cocoa unarchives the .xib file one of the instructions therein says to connect the hide radio button to a variable called hideTicksButton in MainWindowController.swift–but Cocoa can’t find the hideTicksButton variable.

To get rid of the error, select your .xib file and right click on File’s Owner, then you can delete the connection to your non-existent variable.

How do you make sure that your radio buttons are part of the same group?

The only way I was able to make one radio button disable the other was with the following:

[code] @IBAction func showSliderTics(sender: NSButton) {
hideSliderTicsButton.state = NSOffState
slider.numberOfTickMarks = 10

@IBAction func hideSliderTics(sender: NSButton) {
    showSliderTicsButton.state = NSOffState
    slider.numberOfTickMarks = 0

If I don’t explicitly change the other radio button’s state to off when I click one, they stay in the on state.

By connecting them all to the same action. See the discussion here:


And here:


Hmm, that does make sense I hadn’t thought of that. What if you had more than two radio buttons in the same group? How would you differentiate between 3 or more radio buttons states inside the function?

Connect them all to the same action, and if you set one of them to ON, then all the others will automatically be set to OFF.

I’m not quite sure what you are asking there, but you don’t identify buttons by their state, you identify buttons by their tag: Attributes Inspector > View section > Tag.