2

I have a button which I want to disable when my timer ends in Xcode but to disable to button it needs to be an outlet. However, I need it to be an action because it's an important button.

Code:

import UIKit

class ViewController: UIViewController {

    var count = 0
    var timer = 60
    var highScore = 0

    @IBOutlet weak var output: UILabel!
    @IBOutlet weak var timerText: UILabel!
    @IBOutlet weak var scoreText: UILabel!
    @IBOutlet weak var highscoreText: UILabel!

    @IBAction func buttonOne(_ sender: Any) {
        count += 1
        output.text = String(count)
    }

    @IBAction func StartButton(_ sender: Any) {
        Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: Selector(("updateCounting")), userInfo: nil, repeats: true)
    }

    @objc func updateCounting(){
        if timer > 0 {
        timer -= 1
        timerText.text = String(timer)
        } else {
            buttonOneOutlet.isEnabled = false
            timerText.text = "Time up!"
            scoreText.text = "Score: " + String(count)
            if count > highScore {
                highScore = count
                highscoreText.text = String(count)
            } else {
                highscoreText.text = String(highScore)
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}
OscarF123
  • 31
  • 2
  • 8
  • @oscarF123- Please read and follow below links 1. https://stackoverflow.com/questions/32572305/iboutlet-and-ibaction-in-swift 2. https://www.hackingwithswift.com/read/2/5/from-outlets-to-actions-creating-an-ibaction – Devendra Agnihotri Aug 04 '19 at 12:34
  • The button can have both an `@IBAction` _and_ an `@IBOutlet`.] – Rob Aug 04 '19 at 15:46

3 Answers3

2

I think you made some confusion between IBOutlet and IBAction.

Actually here is the difference:

"You need to specify IBAction for methods that will be used in Interface Builder and IBOutlet for objects that will be used in Interface Builder"

(Source - StackOverflow)


I changed your code a little, starting from buttonOneOutlet (IBOutlet) and buttonOne (IBAction).

I added an IBOutlet called buttonOne and I renamed your IBActions like buttonOneTouched and startButtonTouched. Here you can find some documentation about naming conventions in Swift.

Moreover I added a variable called timerObject, so that you can keep a reference to the running timer and invalidate() it later. Otherwise the timer would be running forever.

Here is the updated code:

import UIKit
class ViewController: UIViewController {

    var count = 0
    var timer = 60
    var highScore = 0
    // new timer object declared here
    var timerObject = Timer()

    // new IBOutlet object declared here
    @IBOutlet weak var buttonOne: UIButton!
    @IBOutlet weak var output: UILabel!
    @IBOutlet weak var timerText: UILabel!
    @IBOutlet weak var scoreText: UILabel!
    @IBOutlet weak var highscoreText: UILabel!

    // renamed the function to 'buttonOneTouched' (it was 'buttonOne')
    @IBAction func buttonOneTouched(_ sender: Any) {
        count += 1
        output.text = String(count)
    }

    // renamed the function to 'startButtonTouched' (it was 'StartButton')
    @IBAction func startButtonTouched(_ sender: Any) {
        timerObject = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: Selector(("updateCounting")), userInfo: nil, repeats: true)
    }

    @objc func updateCounting() {
        if timer > 0 {
            timer -= 1
            timerText.text = String(timer)
        } else {
            // added step to invalidate the running timer loop
            timerObject.invalidate()
            // replaced 'buttonOneOutlet' with 'buttonOne'
            buttonOne.isEnabled = false
            timerText.text = "Time up!"
            scoreText.text = "Score: " + String(count)
            if count > highScore {
                highScore = count
                highscoreText.text = String(count)
            } else {
                highscoreText.text = String(highScore)
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}
Andrea Corsini
  • 197
  • 1
  • 9
0

You can do it in the same way as you are doing for those Labels

  1. Define the button in your ViewController.

    @IBOutlet weak var buttonOneOutlet: UIButton!
    
  2. Set the IBOutlet from your Storyboard to that button, by control drag.

Hope it helps

Bhavin Kansagara
  • 2,866
  • 1
  • 16
  • 20
0

Here are the steps you can follow-

For @IBOutlet

1.Declare Your Interface builder Element property just after class name as you already declared for UIlabel

class ViewController: UIViewController{
    @IBOutlet weak var btnTest : UIButton! //Your Interface builder Element

2.Hook the IB Element From Storyboard enter image description here

For @IBAction

1.Write A method inside your class(say SomeViewController)

@IBAction func didTapTestBtn(_sender : AnyObject){
//write your code here.
}

2.Hook the method from Storyboard.

enter image description here