How to show a popup after 20 sec of an app open every time in swift - ios

I need to show a popup every time when i open the app after 20 sec.
code: with this code i can show popup only when i open the app first time after 20 sec.. but i need to show the same when i close the app and open again.. how to do that? please guide me.
var timer = Timer()
override func viewDidLoad() {
timer = Timer.scheduledTimer(timeInterval: 20.0, target: self, selector: #selector(displayAlert), userInfo: nil, repeats: false)
}
#objc func displayAlert()
{
print("after 20 sec")
showPopup()
}

You want to register for notification when your app becomes active...
For example:
override func viewDidLoad() {
super.viewDidLoad()
// all your normal stuff...
// register to receive notification when App becomes active
NotificationCenter.default.addObserver(self, selector: #selector(startAlertTimer), name: UIApplication.didBecomeActiveNotification, object: nil)
}
#objc func startAlertTimer()
{
print("start 20 sec timer")
Timer.scheduledTimer(timeInterval: 20.0, target: self, selector: #selector(showPopup), userInfo: nil, repeats: false)
}
#objc func showPopup() {
print("after 20 seconds, popup")
}

And if you use a DispatchQueue:
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
// Do something here..
}

Related

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)

Can't invalidate timer swift

In my app I should use multiple timers but I don't want to add separate timers for every function, how can I create one function that simplifies creating multiple timers, I tried this code below, it works but I can't invalidate timers.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var first: UILabel!
#IBOutlet weak var second: UILabel!
var count = 0
var count2 = 0
var timer = Timer()
var timer2 = Timer()
override func viewDidLoad() {
super.viewDidLoad()
timerWithDifferentIntervals(myTimer: timer, interval: 1, target: self, selector: #selector(handle1), userInfo: nil, repeats: true)
timerWithDifferentIntervals(myTimer: timer2, interval: 1/6, target: self, selector: #selector(handle2), userInfo: nil, repeats: true)
}
func handle1() {
count += 1
first.text = "\(count)"
}
func handle2() {
count2 += 1
second.text = "\(count2)"
}
func timerWithDifferentIntervals(myTimer: Timer, interval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool) {
var timers = myTimer
timers = Timer.scheduledTimer(timeInterval: interval, target: target, selector: selector, userInfo: userInfo, repeats: repeats)
}
#IBAction func stop(_ sender: UIButton) {
timer.invalidate()
timer2.invalidate()
}
}
You never actually assign a new value to your variables. The timers you create are not saved anywhere, therefore you cannot invalidate them.
I would recommend the following changes:
var timer: Timer? {
didSet {
oldValue?.invalidate()
}
}
var timer2: Timer? {
didSet {
oldValue?.invalidate()
}
}
This will make sure the previous timer is always invalidated when assigning a new one. You can then invalidate using timer = nil or timer2 = nil.
Also, you should return the timer from your method:
func timerWithDifferentIntervals(interval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool) -> Timer {
return Timer.scheduledTimer(timeInterval: interval, target: target, selector: selector, userInfo: userInfo, repeats: repeats)
}
and use it in following way:
timer = timerWithDifferentIntervals(interval: 1, target: self, selector: #selector(handle1), userInfo: nil, repeats: true)
Although the method does basically nothing now, so there is no need for it
Add NStimers in an array, and each timer have a tag of its own.
Then whenever you want to invalidate a timer, reach it via the array and invalidate it.
Hope this helps!
I'm thinking you should use below code for timer create and invalidate
var timer : NSTimer?
func startTimer(_ timeInterval: Int, _ isRepeat: Bool)
{
if timer == nil {
timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: "timerFired", userInfo: nil, repeats: isRepeat)
}
}
func stopTimer()
{
if timer != nil {
timer!.invalidate()
timer = nil
}
}

Timer.scheduledTimer Swift 3 pre-iOS 10 compatibility

I need to schedule a Timer for firing a function every second but I see that in Xcode 8 beta 3 the scheduledTimer is only available for iOS 10.
Is there any alternative for using the timer in iOS 9 or previous versions?
Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { (timer) in print("Hi!")})
Solved using
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(self.updateTime),
userInfo: nil,
repeats: true)
Run a timer with swift3,
var timer: Timer?
func startTimer() {
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.loop), userInfo: nil, repeats: true)
}
}
func stopTimer() {
if timer != nil {
timer?.invalidate()
timer = nil
}
}
func loop() {
let liveInfoUrl = URL(string: "http://192.168.1.66/api/cloud/app/liveInfo/7777")
let task = URLSession.shared.dataTask(with: liveInfoUrl! as URL) {data, response, error in
guard let data = data, error == nil else { return }
print(String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) ?? "aaaa")
}
task.resume()
}
Release the timer when you not use it.
Once scheduled on a run loop, the timer fires at the specified
interval until it is invalidated. A nonrepeating timer invalidates
itself immediately after it fires. However, for a repeating timer, you
must invalidate the timer object yourself by calling its invalidate()
method.
Here is sample code workable with compatibility:
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: 15.0, repeats: true){_ in
// Your code is here:
self.myMethod()
}
} else {
Timer.scheduledTimer(timeInterval: 15.0, target: self, selector: #selector(self.myMethod), userInfo: nil, repeats: true)
}
//Your method or function:
// MARK: - Method
#objc func myMethod() {
print("Hi, How are you.")
}
Swift 3
func runCode(in timeInterval:TimeInterval, _ code:#escaping ()->(Void))
{
DispatchQueue.main.asyncAfter(
deadline: .now() + timeInterval,
execute: code)
}
func runCode(at date:Date, _ code:#escaping ()->(Void))
{
let timeInterval = date.timeIntervalSinceNow
runCode(in: timeInterval, code)
}
func test()
{
runCode(at: Date(timeIntervalSinceNow:2))
{
print("Hello")
}
runCode(in: 3.0)
{
print("World)")
}
}
Updated for swift 3:
If you want to use Timer for some delay or any other purpose used below lines of code in your project;
// function defination:
func usedTimerForDelay() {
Timer.scheduledTimer(timeInterval: 0.3,
target: self,
selector: #selector(self.run(_:)),
userInfo: nil,
repeats: false)
}
func run(_ timer: AnyObject) {
print("Do your remaining stuff here...")
}
// function call:
self.usedTimerForDelay()
NOTE:- you can change the time interval as you want.
//Enjoy coding..!
Timer.scheduledTimer
Put it in the main thread.
You can use the following simple shim to provide the new block-based Timers to pre-iOS 10:
class TimerShim {
private var timer: Timer?
private let block: (Timer) -> Void
private init(timeInterval interval: TimeInterval, repeats: Bool, block: #escaping (Timer) -> Void) {
self.block = block
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(timerDidFire), userInfo: nil, repeats: repeats)
}
class func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: #escaping (Timer) -> Void) -> Timer {
return TimerShim(timeInterval: interval, repeats: repeats, block: block).timer!
}
#objc private func timerDidFire() {
block(timer!)
}
}
Usage example:
TimerShim.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
print("boom!")
}
The correct form is:
Timer.scheduledTimer(withTimeInterval: 2, repeats: false){_ in
"Here your code method"
}

Swift: Reload alamofire request every 10 seconds

I am trying to get information from an alamofire request and I want the information to be updated every 10 seconds. In other words, I want it to refresh. So I want it to repeat the http request every 10 seconds. Does anyone know how to do this?
override func viewDidLoad() {
super.viewDidLoad()
var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self,selector: "execute", userInfo: nil, repeats: true)
}
func execute() {
// insert logic here
}
Check out NSTimer
Example :
NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: #selector(yourUpdatedFunctionHere), userInfo: nil, repeats: true)
Swift 4 & 5
override func viewDidLoad() {
super.viewDidLoad()
_ = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(execute),
userInfo: nil,
repeats: true)
}
#objc func execute() {
print("Hello")
}
This Will Execute in every 5 seconds

How can I use Timer (formerly NSTimer) in Swift?

I tried
var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)
But, I got an error saying
'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
This will work:
override func viewDidLoad() {
super.viewDidLoad()
// Swift block syntax (iOS 10+)
let timer = Timer(timeInterval: 0.4, repeats: true) { _ in print("Done!") }
// Swift >=3 selector syntax
let timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
// Swift 2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyClass.update), userInfo: nil, repeats: true)
// Swift <2.2 selector syntax
let timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)
}
// must be internal or public.
#objc func update() {
// Something cool
}
For Swift 4, the method of which you want to get the selector must be exposed to Objective-C, thus #objc attribute must be added to the method declaration.
Repeated event
You can use a timer to do an action multiple times, as seen in the following example. The timer calls a method to update a label every half second.
Here is the code for that:
import UIKit
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
#IBOutlet weak var label: UILabel!
// start timer
#IBAction func startTimerButtonTapped(sender: UIButton) {
timer.invalidate() // just in case this button is tapped multiple times
// start the timer
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
// stop timer
#IBAction func cancelTimerButtonTapped(sender: UIButton) {
timer.invalidate()
}
// called every time interval from the timer
func timerAction() {
counter += 1
label.text = "\(counter)"
}
}
Delayed event
You can also use a timer to schedule a one time event for some time in the future. The main difference from the above example is that you use repeats: false instead of true.
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
The above example calls a method named delayedAction two seconds after the timer is set. It is not repeated, but you can still call timer.invalidate() if you need to cancel the event before it ever happens.
Notes
If there is any chance of starting your timer instance multiple times, be sure that you invalidate the old timer instance first. Otherwise you lose the reference to the timer and you can't stop it anymore. (see this Q&A)
Don't use timers when they aren't needed. See the timers section of the Energy Efficiency Guide for iOS Apps.
Related
How to work with dates and time in Swift
Updated to Swift 4, leveraging userInfo:
class TimerSample {
var timer: Timer?
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(eventWith(timer:)),
userInfo: [ "foo" : "bar" ],
repeats: true)
}
// Timer expects #objc selector
#objc func eventWith(timer: Timer!) {
let info = timer.userInfo as Any
print(info)
}
}
As of iOS 10 there is also a new block based Timer factory method which is cleaner than using the selector:
_ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
label.isHidden = true
}
Swift 5
I personally prefer the Timer with the block closure:
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
// TODO: - whatever you want
}
Swift 3, pre iOS 10
func schedule() {
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
}
}
#objc private func timerDidFire(timer: Timer) {
print(timer)
}
Swift 3, iOS 10+
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
print(timer)
}
}
Notes
It needs to be on the main queue
Callback function can be public, private, ...
Callback function needs to be #objc
Check with:
Swift 2
var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
Swift 3, 4, 5
var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
You will need to use Timer instead of NSTimer in Swift 3.
Here is an example:
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(YourController.update),
userInfo: nil,
repeats: true)
// #objc selector expected for Timer
#objc func update() {
// do what should happen when timer triggers an event
}
First declare your timer
var timer: Timer?
Then add line in viewDidLoad() or in any function you want to start the timer
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)
This is the func you will callback it to do something it must be #objc
#objc func action () {
print("done")
}
for swift 3 and Xcode 8.2
(nice to have blocks, but if You compile for iOS9 AND want userInfo):
...
self.timer = Timer(fireAt: fire,
interval: deltaT,
target: self,
selector: #selector(timerCallBack(timer:)),
userInfo: ["custom":"data"],
repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
self.timer!.fire()
}
func timerCallBack(timer: Timer!){
let info = timer.userInfo
print(info)
}
SimpleTimer (Swift 3.1)
Why?
This is a simple timer class in swift that enables you to:
Local scoped timer
Chainable
One liners
Use regular callbacks
Usage:
SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs
Code:
class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
typealias Tick = ()->Void
var timer:Timer?
var interval:TimeInterval /*in seconds*/
var repeats:Bool
var tick:Tick
init( interval:TimeInterval, repeats:Bool = false, onTick:#escaping Tick){
self.interval = interval
self.repeats = repeats
self.tick = onTick
}
func start(){
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
}
func stop(){
if(timer != nil){timer!.invalidate()}
}
/**
* This method must be in the public or scope
*/
#objc func update() {
tick()
}
}
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
And Create Fun By The Name createEnemy
fund createEnemy ()
{
do anything ////
}
In Swift 3 something like this with #objc:
func startTimerForResendingCode() {
let timerIntervalForResendingCode = TimeInterval(60)
Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
target: self,
selector: #selector(timerEndedUp),
userInfo: nil,
repeats: false)
}
#objc func timerEndedUp() {
output?.timerHasFinishedAndCodeMayBeResended()
}
If you init method of timer
let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)
func update(_ timer : Timer) {
}
then add it to loop using method other selector will not be called
RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)
NOTE : If you are want this to repeat make repeats true and keep the reference of timer otherwise update method will not be called.
If you are using this method.
Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)
keep a reference for later use if repeats is true.
I tried to do in a NSObject Class and this worked for me:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
print("Bang!") }
NSTimer has been renamed to Timer in Swift 4.2.
this syntax will work in 4.2:
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)

Resources