Button needs to be disapear and come back - swift

I've got now an app that if you click on a button it will disappear, now I want to make the button disappear even when your not clicking on that button, but it will come back in a few seconds (or even less than a second). On the moment this is how the button looks in the code.
#IBAction func increaseCount(button: UIButton) -> Void {
button.hidden = true
ourScore.text = "\(++score)"
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(Double((arc4random_uniform(1) + 2)) * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
button.hidden = false
}
}
How is it possible to make the button disappear even when your not clicking it, but it will come back in just a few seconds (and less than a second) back? The time should be random between 2 and a half second. When your clicking it should also disappear and it will come back less than 2 seconds.
Who could help me?

This code will have the button appear and reappear on its own every 2 seconds. You can modify the time so it is random (if you need help with that, let me know).
Link your button on the story board and the code below should do the trick.
#IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.hidden = true
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "appear:", userInfo: self, repeats: false)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func appear(timer: NSTimer) {
self.button.hidden = true
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "disappear:", userInfo: self, repeats: false)
}
func disappear(timer: NSTimer) {
self.button.hidden = false
NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "appear:", userInfo: self, repeats: false)
}
EDIT: For the button to disappear when clicked, register an Action event from the button and use the code:
#IBAction func clicked(sender: UIButton) {
self.button.hidden = true
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "appear:", userInfo: self, repeats: false)
}
Again, this hides it just for 1 second when it is clicked, but you can change the time to be random.
Edit 2: You should see this:

Related

scheduledTimer not firing if I navigate to two viewcontrollers

I have a weak scheduledTimer:
weak var timer = Timer.scheduledTimer(timerInterval: 2.0, target: self, selector: #selector(fire), userInfo: ["id",id], repeats: false)
If I begin this timer and navigate to only one viewController, it will fire in the background with no issue. However, if I navigate to a second viewController before the timer fires, it will never go off. Any idea why this is happening?
To define
class viewController: UIViewController
{
var timer = Timer()
use in other function
func one()
{
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(backClick), userInfo: ["id"], repeats: false)
}
func two()
{
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(backClick), userInfo: ["id"], repeats: false)
}
inValidate() timer
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
timer.fire()
}
Because of that was weak like #Alexandr Kolesnik 's comment, or may be you invalidated when first one is disappeared.

Countdown speeds up when the button that starts it is pressed multiple times

I just started to learn swift . and I found when using a button to start a count down if i pressed the button twice it speeds up the process. What to add to prevent that?
#IBAction func startButton(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(processTime), userInfo: nil, repeats: true)
}
#objc func processTime(){
if counter > 0 {
counter -= 1
timeLabel.text = "\(counter)"
}else {
timer.invalidate()
}
}
I tried to use sender.isEnabled = false it gave this error (Value of type 'Any' has no member 'isEnabled')
so I did it like this :
#IBAction func startButton(_ sender: Any) {
if timer.isValid != true{
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(processTime), userInfo: nil, repeats: true)
}
}
Many ways, depends on what logic you prefer.
Basically you need to ensure that the timer starts only once until it completes.
In the following example, we start the timer only if it's not been initialized previously.
Furthermore, when we stop the timer, we explicitly set it to nil so the following logic works again after the timer completes.
//globally declared as optional
var timer: Timer?
#IBAction func startButton(_ sender: Any) {
//check if timer is nil
if timer != nil {
//start timer only if timer is nil
timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(processTime),
userInfo: nil,
repeats: true)
}
}
#objc func processTime() {
if counter > 0 {
counter -= 1
timeLabel.text = "\(counter)"
}
else {
timer.invalidate()
//clear the timer
timer = nil
}
}
add a sender.isEnabled = false and after you press the button once it won't be clickable again
You need to invalidate the timer by calling timer.invalidate() before you reassign a new timer. If you assign a new timer instance to the old one without invalidating, you will lose reference to it and it will never be invalidated.

swift xcode - disable UIbutton from being pressed once Timer is running

I have a button called start that starts the TIMER counting , I want to disable it from being pressed again when the TIMER is counting other wise it makes the TIMER start counting twice as fast.
#IBAction func start(_ sender: Any) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(CountUpVC.action), userInfo: nil, repeats: true)
Thanks in advance.
It's best done with an observer on the timer:
var timer : Timer? {
didSet {
start.isEnabled = !(timer?.isValid ?? false)
}
}
When you invalidate it, you should set it to nil to trigger didSet and enable the button again:
timer?.invalidate()
timer = nil

SWIFT: invalidate()

I use NSTimer in swift
I start NSTimer on mainViewController and when I click on button I move to another view (type: Modal) and timer works in Background Everything's OK, but when I back main viewController my timer is duplicated so... How to stop timer on antoher View?
override func viewDidLoad() {
super.viewDidLoad()
countDownTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerDown", userInfo: nil, repeats: true)
}
If viewDidLoad executes again when you "come back" from your modal view, you're probably not actually coming back but triggering a segue to a new instance. If you return to the main view using an unwind segue, viewDidLoad will not execute again and you will be on your original instance if you need to stop the timer.
As I understood your goal is that you don't duplicate the timer.
In order to do this you can simply check if the timer is null...
override func viewDidLoad() {
super.viewDidLoad()
if(countDownTimer==nil)
{
countDownTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerDown", userInfo: nil, repeats: true)
}
}

How can I pause and resume NSTimer.scheduledTimerWithTimeInterval in swift?

I'm developing a game and I want to create a pause menu. Here is my code:
self.view?.paused = true
but NSTimer.scheduledTimerWithTimeInterval still running...
for var i=0; i < rocketCount; i++ {
var a: NSTimeInterval = 1
ii += a
delaysShow = 2.0 + ((stimulus + interStimulus) * ii)
var time3 = NSTimer.scheduledTimerWithTimeInterval(delaysShow!, target: self, selector: Selector("showRocket:"), userInfo: rocketid[i], repeats: false)
}
I want time3 to pause the timer when player click pause menu and continue run the timer when player come back to the game, but how can I pause NSTimer.scheduledTimerWithTimeInterval? help me please.
You need to invalidate it and recreate it. You can then use an isPaused bool to keep track of the state if you have the same button to pause and resume the timer:
var isPaused = true
var timer = NSTimer()
#IBAction func pauseResume(sender: AnyObject) {
if isPaused{
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("somAction"), userInfo: nil, repeats: true)
isPaused = false
} else {
timer.invalidate()
isPaused = true
}
}
To Start:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)
To Resume:
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)
To Pause:
timer.invalidate
This worked for me. The trick is that do not look for something like "timer.resume" or "timer.validate". Just use "the same code for starting a timer" to resume it after the pause.
To start
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
To pause
timer.invalidate()
To reset
time += 1
label.text = String(time)
'label' is the timer on output.
I was just working through a similar problem with my game, and found an easy solution.
First I should point out like others have, that Timer and NSTimer doesn't have a pause function. You have to stop the Timer with Timer.invalidate(). After invalidating a Timer, you must initialize it again to start the Timer. To quote from https://developer.apple.com/documentation/foundation/timer, the function .invalidate() -
Stops the timer from ever firing again and requests its removal from
its run loop.
To pause a timer we can use Timer.fireDate, this is where Timer (and NSTimer) saves the date for when the Timer will fire in the future.
Here's how we can pause a Timer by saving the seconds left that the Timer has until it fires again.
//The variable we will store the remaining timers time in
var timeUntilFire = TimeInterval()
//The timer to pause
var gameTimer = Timer.scheduledTimer(timeInterval: delaysShow!, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)
func pauseTimer()
{
//Get the difference in seconds between now and the future fire date
timeUntilFire = gameTimer.fireDate.timeIntervalSinceNow
//Stop the timer
gameTimer.invalidate()
}
func resumeTimer()
{
//Start the timer again with the previously invalidated timers time left with timeUntilFire
gameTimer = Timer.scheduledTimer(timeInterval: timeUntilFire, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)
}
Note: Don't invalidate() the Timer before getting the fireDate. After invalidate() is called the Timer seems to reset the fireDate to 2001-01-01 00:00:00 +0000.
2nd Note: A timer can potentially fire after its set fireDate. This will lead to a negative number, which will default the Timer to run after 0.1 milliseconds instead. https://developer.apple.com/documentation/foundation/timer/1412416-scheduledtimer
To stop it
time3.invalidate()
To start it again
time3.fire()
You can not resume the timer back.
Instead of resuming - just create a new timer.
class SomeClass : NSObject { // class must be NSObject, if there is no "NSObject" you'll get the error at runtime
var timer = NSTimer()
init() {
super.init()
startOrResumeTimer()
}
func timerAction() {
NSLog("timer action")
}
func pauseTimer() {
timer.invalidate
}
func startOrResumeTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("timerAction"), userInfo: nil, repeats: true)
}
}
Even though the solutions exposed here are good, I thought an important insight was missing. Like a lot of people here explained, timer invalidate() and recreate is the best option. But one could argue that you could do something like this:
var paused:Bool
func timerAction() {
if !paused {
// Do stuff here
}
}
is easier to implement, but it will be less efficient.
For energy impact reasons, Apple promotes avoiding timers whenever possible and to prefer event notifications. If you really need to use a timer, you should implement pauses efficiently by invalidating the current timer. Read recommendations about Timer in the Apple Energy Efficiency Guide here:
https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/MinimizeTimerUse.html
SWIFT3
Global Declaration :
var swiftTimer = Timer()
var count = 30
var timer = Timer()
#IBOutlet weak var CountDownTimer: UILabel!
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
BtnStart.tag = 0
}
Triggered IBACTION :
#IBAction func BtnStartTapped(_ sender: Any) {
if BtnStart.tag == 0 {
BtnStart.setTitle("STOP", for: .normal)
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ScoreBoardVC.update), userInfo: nil, repeats: true)
BtnStart.tag = 1
} else {
BtnStart.setTitle("START", for: .normal)
timer.invalidate()
BtnStart.tag = 0
}
}
Function that Handles The things :
func update(){
if(count > 0){
let minutes = String(count / 60)
let ConvMin = Float(minutes)
let minuttes1 = String(format: "%.0f", ConvMin!)
print(minutes)
let seconds = String(count % 60)
let ConvSec = Float(seconds)
let seconds1 = String(format: "%.0f", ConvSec!)
CountDownTimer.text = (minuttes1 + ":" + seconds1)
count += 1
}
}
Pause timer : timer.invalidate()
and
Resume timer : recreate timer. it's work fine.
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(mainController.updateTimer), userInfo: nil, repeats: true)