Add delay for order counter with Operation Queue - ios

I want to add a button with one purpose, when the user click, it'll add one more product to the chart.
The thing in my mind is, I'll create a counter, if the user click faster than 0.5 seconds, counter will increase, but the value will not go to the server. When users last click is more than 1 second ago, last value of the counter will go to the server as the order amount. My goal is, if user will add, for example 10 amount of same order very fast, I don't want to send all clicks one by one to the server, instead send all clicks sum (which is the counter value) at once when 1 second passed after last user click.
I saw people says it can be done with NSOperations. But I couldn't figure out how.
var counter = 0
#IBAction func addProductAmount (_ sender: Any) {
// 1. Increase counter
// 2. If only 0.5 seconds or less time passed, don't send the counter value, wait it to be 1 seconds
// 3. Send counter value 1 seconds after last user click
}
Code will be something like this. But how can use Operation Queue for this? Any help?
I'm learning swift and I don't know Objective-C at all.

The thing you want to do is called throttling. So you can use this code:
var counter = 0
timer: Timer?
#IBAction func addProductAmount (_ sender: Any) {
counter += 1
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(sendRequest), userInfo: nil, repeats: false)
}
func sendRequest() {
// your method to make a request to the server
}

Related

How to show Multiple timers at same screen using one function in Swift ios [duplicate]

This question already has an answer here:
Show Multiple Counter in label but at same screen (Swift, IOS)
(1 answer)
Closed 5 months ago.
In my app I have spots on which a user can tap to unlock them, a user can unlock multiple spots at the same time and there can be different number of spots every time, whenever a user unlocks a spot i want to show a timer of 60 seconds on the unlocked spot, So, there can be multiple timers on same screen all having different counts. For example if a user unlocks 2 spots with the difference of 30 seconds. the timer on spot 1 should be 30 seconds left and spot 2 should be 60 seconds left. I only have 1 function for doing this task I can easily show timer on 1 spot but showing them on multiple places, multiple times is very complex. I am sharing a picture too for reference. any help would be appreciated.
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
#objc func updateCounter() {
if counter > 0 {
let time = Int(counter/60)
let dec = Int(counter.truncatingRemainder(dividingBy: 60))
spotTiming = String(time) + ":" + String(dec)
}
counter -= 1
}
i want to show timers where counter is written
You can use a timer as a trigger to update the UI every x period (example: 0.5s). You save time remaining every spots at a variable as Array and reduce each element when timer was triggered.
let step = TimeInterval(0.5)
timer = Timer.scheduledTimer(timeInterval: step, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
var timer_remainings = [TimeInterval]()
#objc func updateCounter() {
for (index, item) in timer_remainings.enumerated() {
timer_remainings[index] = max(0.0, timer_remainings - step)
}
// Update UI
updateUI()
}

how to create countdowns in swift that will start after a countdown has finished

[New to Swift]
I am making an app on Swift 5 that displays time left before my next task is to start.
My app:
Task 1: Start at 9.30 am
Task 2: Start at 10.15 am
Let's say Current Time: 09.00 am
Countdown: Time before next task start = 00:30:02 --> 00:30:01 ...
I would like to display countdown of the nearest task.
Currently, I can only have one countdown timer on my viewonLoad() that picks up the current countdown. It continues and once it finishes it does not start next timer after it has finished. I understand I have to deal with Background state at a later date, but since I am slowly starting. My idea is to make sure I can initiate next countdown timer once my current one has expired.
So at any point when I open my app, it will always display countdown till my next task.
var count = 30 // calculation simplified ... this data is calc from two different date obj
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
#objc func update() {
if(count > 0) {
count = count - 1
countdownLabel.text = String(count)
}else{
timer!.invalidate()
getNextTaskTimes()
}
}
func getNextTaskTimes(){
count = 5 // not working
}
How can I achieve this please? Also, is there a better way of doing this? Given that, my user may choose to close the app and come back at a later time, I still would want my countdown to continue in the background.
Any help is appreciated. :D Thanks
I realized the above code works. I just need to make sure I do not invalidate the timer in the else block. Invalidating the timer just kills it.

Multiple timers at once ios

I am making an app where the user can have multiple timers going at once and see them in a list view.
I am aware that there are 2 main options for working out time:
Subtract the date started from current date (current date-start date)
OR
Use an NSTimer and take away 1 second every second from each active timer.
I have previously been using the latter, but having looked around the internet I am starting to think that the data one may be better.
Please could you let me know which you think is best to use, and if you chose the first one (dates), please could you provide some sample code on how to use it.
You can Use an NSTimer and take away 1 second every second from each active timer. You can use this class.
class CustomTimer {
typealias Update = (Int)->Void
var timer:Timer?
var count: Int = 0
var update: Update?
init(update:#escaping Update){
self.update = update
}
func start(){
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerUpdate), userInfo: nil, repeats: true)
}
func stop(){
if let timer = timer {
timer.invalidate()
}
}
/**
* This method must be in the public or scope
*/
#objc func timerUpdate() {
count += 1;
if let update = update {
update(count)
}
}
}
To use multiple timer you can create multiple instance of CustomTimer, Example Code:
let timer1 = CustomTimer { (seconds) in
// do whatever you want
}
timer1.start()
let timer2 = CustomTimer { (seconds) in
// do whatever you want
}
timer2.start()
NOTE:
timerUpdate method will be called exactly at 1 second interval. to keep some space for function execution we can set interval to 0.9 or 0.95 according to time taken by execution.
You use both. You have one Timer that repeats every second. The handler for the Timer then iterates through your list of start dates for each of the user's timers and you update the display for each based on the current date.

Time Took Variable in Swift

Overview: I am trying to create quiz game where someone has to answer questions in a certain amount of time. They have 10 seconds to solve each question or it will move to the next controller. The problem is that whenever I click next question before the full time is up it keeps counting down to 10. What should happen is it should stop counting time for that question.
So far I have implemented the following code to try to make this work. var time = 0 and first created a global variable called time. Then I created timer code as following, var count = 10 #IBOutlet var countDownLabel: UILabel!
Then I create a label that will tick down every second until it reaches 0. Code as follows:
if(count > 0) {
countDownLabel.text = String(count)
count -= 1
time += 1
}
print (time)
if (count <= 0 ) {
count = 10
self.performSegue(withIdentifier:"NextQuestion1", sender: nil)
}
Summary: Everytime count goes down time should go up. Then at the end it will display the time they. I would gladly appreciate some help on this problem.
When you click on the next button, you need to invalidate the timer so that it will stop counting.
Say you created your timer in this way
let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(YourSegueFunction), userInfo: nil, repeats: false)
Then when you click on the next button, use the following line of code to stop the timer
timer.invalidate()
Here is the demo

How to measure how long specific actions take to complete for users in iOS app

I have an iOS app that I wrote with Swift with Firebase Auth/DB for the backend. I would like to measure how long it takes for a user to complete specific actions. I'm actually not interested in the response time, but am interested in the total time it takes to complete something.
In other words, I want to measure how long it takes to login, click on a button, receive a push notification, click "Ok" on that notification, etc. I also want to log how many seconds it took to get from one thing to the next (i.e. login time: 2.5 seconds, time to push a specific button: 4 seconds, etc.).
I am trying out Firebase Analytics, and it almost works, but not quite. I can log specific events, such as login, button presses, etc., but it just logs the that the event occurs, not how long it took.
Ideally, I would record all of this data on the specific users I give to try my app, so I could look at all the data, find averages and other useful information.
consider using a a Timer, maybe something like this.
import UIKit
class Whatever: UIViewController {
var timer = Timer()
var currentTime = 0.00
func timeCounter() {
currentTime += 0.01
}
override func viewDidLoad() {
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(Whatever.timeCounter), userInfo: nil, repeats: true)
}
#IBAction func buttonPressed(_ sender: Any) {
timer.invalidate()
//whatever button does
}
}
This way when the application begins the timer will begin, when the final button is pushed the timer will stop. You will have the value of how long it took stored as currentTime.
Hope this helps!

Resources