16

I am in the process of learning swift. I would like to know how to call a function programmatically if a button is pressed. I tried this, but the function is executed directly when the program launches, not when I press the button. Can you please help me to fix this.

Here is what i have tried,

//
//  ViewController.swift
//  hjkhjkjh
//
//  Created by iznogoud on 14/05/16.
//  Copyright © 2016 iznogoud. All rights reserved.
//

import Cocoa


class ViewController: NSViewController {

    func printSomething() {
       print("Hello")
    }

    override func viewDidLoad() {
       super.viewDidLoad()

       let myButtonRect = CGRect(x: 10, y: 10, width: 100, height: 10)
       let myButton =  NSButton(frame: myButtonRect)
       view.addSubview(myButton)
       myButton.target = self
       myButton.action = Selector(printSomething())


       // Do any additional setup after loading the view.
    }

    override var representedObject: AnyObject? {
       didSet {
          // Update the view, if already loaded.
       }
    }
}
Anjali Kevadiya
  • 3,567
  • 4
  • 22
  • 43
iznogoud
  • 173
  • 1
  • 1
  • 4

1 Answers1

22

The problem lies in the way you add your selector

myButton.action = Selector(printSomething())

The syntax for adding selectors is a bit quirky, you give it a string with the name of the function, so in your case you should write:

myButton.action = Selector("printSomething")

Which should reward you with Hello in your console.

And probably because the syntax is causing people problems it was changed in Swift 2.2, so now you write:

myButton.action = #selector(ViewController.printSomething)

instead. This means that the compiler can help you catch these errors early, which is a great step forward I think. You can read more about it in the release notes for Swift 2.2 here

So...here is your entire example:

import Cocoa

class ViewController: NSViewController {

    @objc
    func printSomething() {
        print("Hello")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let myButtonRect = CGRect(x: 10, y: 10, width: 100, height: 10)
        let myButton =  NSButton(frame: myButtonRect)
        view.addSubview(myButton)

        myButton.target = self
        myButton.action = #selector(ViewController.printSomething)
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

Hope that helps you.

pbodsk
  • 6,787
  • 3
  • 21
  • 51
  • 1
    Thank you, this works, and thanks for your excellent explication!! – iznogoud Jun 10 '16 at 09:27
  • What should I do for multiple buttons and also when new button creates at that time previous button frame of y position also be the change. – ronak patel Nov 17 '17 at 12:09
  • @ronakpatel not sure I follow sorry. If you'd like to add more than one button then you'd create said buttons one by one and give them each an individual `rect` (so, create a different `CGRect` for each of them). But you'd probably also create a separate action for each of them. Am I misunderstanding your question? – pbodsk Nov 17 '17 at 13:39
  • In Swift 5.1 they request that an @objc is provided before the function you call. – RichIntellect Sep 30 '19 at 20:22