Changing/looping text in label - ios

I want to make my label change text every 5 seconds from rLabel.text = "\(update) free trial" wait for another 5 second then change it rLabel.text = "upgrade now!" ~ on repeat.
rLabel.text = "\(update) free trial"
if daysLeft <= 5 {
let timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
timer.fire()
}
} else {
rLabel.text = "\(update) free trial"
}
#objc func update() {
rLabel.text = "upgrade now!"
}

You can simply use a boolean to switch the text every 5 sec
override func viewDidLoad() {
let timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
var isShowingText1 = false
#objc func updateText(){
rLabel.text = isShowingText1 ? "Text 2" : "Text 1"
isShowingText1 = !isShowingText1
}

You can keep track of current text by having index property. Also you can use Timer with block closure and you can avoid having Obj-C-ish #selector
var index = 0 {
didSet {
if index > 1 { index = 0 }
}
}
var text: String {
return ["\(update) free trial", "upgrade now!"][index]
}
func foo() {
rLabel.text = text
Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { _ in
self.index += 1
self.rLabel.text = self.text
}
}

Related

How do I solve this error "Argument of '#selector' cannot refer to local function 'updateTimer()'", trying to make countdown timer in swift 5.1

import UIKit
class ViewController : UIViewController {
let eggTimes = ["Soft": 300, "Medium": 420, "Hard": 720]
var secondsRemaining = 60
#IBAction func hardnessSelected(_ sender: UIButton) {
let hardness = sender.currentTitle!
secondsRemaining = eggTimes[hardness]!
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
func updateTimer() {
if secondsRemaining > 0 {
print("\(secondsRemaining) seconds.")
secondsRemaining -= 1
}
}
}
}
I am taking this Udemy course where it seems to be working fine but on my system, it is not working at all.
The action method must be on the top level of the class (the eggTimes level) and must be marked as #objc.
A more convenient solution is the (underestimated) closure-based API of Timer
Replace
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
func updateTimer() {
if secondsRemaining > 0 {
print("\(secondsRemaining) seconds.")
secondsRemaining -= 1
}
}
with
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [unowned self] timer in
if self.secondsRemaining > 0 {
print("\(self.secondsRemaining) seconds.")
self.secondsRemaining -= 1
} else {
timer.invalidate()
}
}

how the countdown timer works in the background

I want to update the counter when the application is thrown into the background and reopened.
First, I added two observers in viewWillAppear like this
NotificationCenter.default.addObserver(self, selector: #selector(pauseApp1), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(startApp1), name: UIApplication.didBecomeActiveNotification, object: nil)
but the countdown timer immediately counts as -1, -2 when the application is first opened. Besides that, I can't update the label the way I want.
#IBOutlet weak var timeDurationLabel: UILabel!
var timer = Timer()
var audioPlayer = AVAudioPlayer()
var remainder: Int = 0
var timeDuration: Int = 0
var countdownInterval: TimeInterval = 0.0
var currentBackgroundDate = Date()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(pauseApp1), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(startApp1), name: UIApplication.didBecomeActiveNotification, object: nil)
}
#objc func pauseApp1() {
timer.invalidate()
currentBackgroundDate = Date()
}
#objc func startApp1() {
let difference = self.currentBackgroundDate.timeIntervalSince(Date())
timeDuration = timeDuration + Int(difference)
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
}
#IBAction func startButtonTapped(_ sender: UIButton) {
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
self.timeDuration = Int(self.countdownInterval) - (self.remainder % 60)
self.startButton.initActionBtn(colorType: .gray, title: "START")
self.coundownPickerButton.isEnabled = false
self.circularProgress.animate(fromAngle: 0, toAngle: 360, duration: TimeInterval(timeDuration)) {
completed in
if completed {
print("animation stopped, completed")
}
else {
print("animation stopped, was interrupted")
}
}
}
#objc func updateCountdown() {
self.timeDuration -= 1
self.timeDurationLabel.text = timeFormatted(timeDuration)
if timeDuration == 0 {
timer.invalidate()
self.audioPlayer.play()
self.startButton.initActionBtn(colorType: .green, title: "START")
}
}
When you say:
let difference = self.currentBackgroundDate.timeIntervalSince(Date())
This is going to produce a negative value, since you're asking for the time interval from now to when you set the current background date. If you want a positive number you should use:
let difference = Date().timeIntervalSince(self.currentBackgroundDate)

how to restart the timer in swift

i am making an application where i am using OTP screen . i worked out with the timer functionality and also able to change the text and show the timer again . my issue is i am not able to restart the timer again. it gets stuck in 00:10.
Here is my following code please Help !!
#IBOutlet weak var butttonName: ButtonDesign!
var countTimer:Timer!
var counter = 10
var restartTimer = false
var isTimerRunning = false
override func viewDidLoad() {
if isTimerRunning == false {
startTimer()}
}
func startTimer() {
self.countTimer = Timer.scheduledTimer(timeInterval: 1 , target: self, selector: #selector(OTPVerificationViewController.changeTitle), userInfo: nil, repeats: true)
isTimerRunning = true
}
#objc func changeTitle()
{
if counter != 0
{
butttonName.setTitle(timeString(time: TimeInterval(counter)), for: .normal)
counter -= 1
butttonName.isEnabled = false
} else {
countTimer.invalidate()
butttonName.setTitle("Resend", for: .normal)
}
}
#IBAction func verifyButton(_ sender: UIButton) {
if butttonName.currentTitle == "Resend" {
print("clicked when name is resend !!!")
if restartTimer == true {
startTimer()
restartTimer = false
}
} else {
print("clicked when it is name is verify")
self.performSegue(withIdentifier: "confirmPassword", sender: self)
}
}
I want to restart the timer whenever the user clicked on "Resend" Button and want to perform segue whenever the user clicked on "Verify" button . both button are the same one i am changing the name on run time
You need to restart the counter too
if butttonName.currentTitle == "Resend" {
counter = 10
// startTimer()
}
Just make the method just like below:
var count = 120
func updateCounter(){
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in
if(self.count > 0){
self.lblTime.text = "\(self.count)"
self.count = self.count-1
}else {
self.lblTime.text = "0"
timer.invalidate()
self.btnresend.isHidden = false // in your case you can change the title of the button
}
})
} else {
// Fallback on earlier versions
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.timerMethod), userInfo: nil, repeats: true)
}
}
#objc func timerMethod() {
if(self.count > 0){
self.lblTime.text = "\(self.count)"
self.count = self.count-1
}else {
self.lblTime.text = "0:0"
self.btnresend.isHidden = false
}
}
And from where you want to restart the time just call the update counter method
with set count 120 or you want
self.count = 120

How to add countdowntimer which will run in whole iOS application?

I need to add a global timer of 60 minutes in the application which will show in all ViewControllers.
But not able to implement this feature.
I have implemented timer in one ViewController till now.
Here is my code:
var timerCount = 3600
var timer = Timer()
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
func update() {
if(timerCount > 0){
let minutes = String(timerCount / 60)
let seconds = String(timerCount % 60)
timeLbl.text = minutes + ":" + seconds
timerCount -= 1
}
else {
timer.invalidate()
let vc = storyboard?.instantiateViewController(withIdentifier: "NavigateViewController")
navigationController?.pushViewController(vc!, animated: true)
}
}
I need to show this timer value in every ViewController of the application.
// Create class TimerManager
class TimerManager {
var timerCount = 3600
static let sharedInstance = TimerManager()
var timer: Timer?
init() {
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
#objc func update() {
if(timerCount > 0){
let minutes = String(timerCount / 60)
let seconds = String(timerCount % 60)
timerCount -= 1
}
else {
self.timer?.invalidate()
}
}
}
// At view Controller you can access timerCount
print(TimerManager.sharedInstance.timerCount)
You should display it in a separate UIWindow instance. Put the label in a separate View Controller and refer to answer 42 from this post:
To create a new UIWindow over the main window
// Create class TimerManager
class TimerManager {
var timerCount = 3600
static let sharedInstance = TimerManager()
var timer: Timer!
init() {
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
#objc func update() {
if(timerCount > 0){
let minutes = String(timerCount / 60)
let seconds = String(timerCount % 60)
timerCount -= 1
}
else {
self.timer?.invalidate()
}
}
}
// At view Controller you can access timerCount
print(TimerManager.sharedInstance.timerCount)

Swift 2 - Timed Actions one second apart?

I'm trying to get output like so:
1 (then a one second delay)
Hello
2 (then a one second delay)
Hello
3 (then a one second delay)
Hello
But instead I get
1
2
3 (then a one second delay)
Hello
Hello
Hello
Here's my for loop invoking the NSTimer
var timer = NSTimer()
for i in 1...3 {
print("\(i)");
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(MainVPScreenViewController.printTest), userInfo: nil, repeats: false)
}
And here's the selector method:
func printTest() {
print("Hello")
}
Thanks in advance for any help you can provide
Try this solution without NSTimer:
var i = 1
func printHello() {
print(i)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
print("Hello")
i +=1
if i <= 3 {
printHello()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
printHello()
}
I need 2 NSTimers to do this, this is my approach
class ViewController: UIViewController {
var i = 1
override func viewDidLoad() {
super.viewDidLoad()
beginPrinting()
}
func beginPrinting() {
var timer2 = NSTimer()
if(i <= 100)
{
timer2 = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.printWithDelay), userInfo: nil, repeats: false)
}
}
func printWithDelay()
{
var timer = NSTimer()
print("\(i)");
i += 1
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.printTest), userInfo: nil, repeats: false)
}
func printTest() {
print("Hello")
beginPrinting()
}
}
Hope this helps you
Use timer with repeat to true. So in your view controller would be like this
var timer = NSTimer()
var counter = 0
var max = 10
let delay = 1 // in second
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self,
selector: #selector(self.printTest), userInfo: nil, repeats: true)
}
func printTest() {
counter += 1
print(counter)
print(hello)
if counter == maxNumber {
timer.invalidate()
}
}
This does it with repeat false, and is set up to be in a playground:
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
#objc class Foo: NSObject {
static var timer = NSTimer()
var i:Int
override init() {
Foo.timer = NSTimer()
i = 1
}
func schedule() {
print("\n\(i)");
i += 1
Foo.timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: #selector(printTest),
userInfo: nil,
repeats: false)
}
#objc func printTest() {
print("Hello")
if i < 5 {
schedule()
}
}
}
let bar = Foo()
bar.schedule()

Resources