How to limit function to once in every x SWIFT

Viewed 205

so I have made a comments option on my app which lets the users comment something on posts. It is directly referenced and sends info from the string to the api endpoint. That works, now I was wondering if there was a way to limit the number of essentially requests to the API so users can send comments once every minute per say

    TextField("Comment...", text: $comment) { editingChanged in
                    } onCommit: {
                        validate()
                        showsAlert = !isValid
                        if isValid{
                            viewModel.sendComment(nickname: nickname, body: comment) {
                                self.comment = ""
                            }
                        }
                    }
                }
                .padding()
                .frame(width: UIScreen.main.bounds.width, height: 80)
                .ignoresSafeArea(.keyboard, edges: .bottom)
                

It would help me reduce spam on the comments and would be a life saver

2 Answers

You can create a simple Swift class to control the time.

public class Time_Control:Thread{

    var wait_time:Int //In seconds
    public var can_send:Bool = true

    init(_ wait_time:Int) {
        self.wait_time = wait_time
    }

    public override func start() {
        super.start()

        self.can_send = false
        Thread.self.sleep(forTimeInterval: TimeInterval(self.wait_time))
        self.can_send = true
    }
}

Then you can use this object in any part of your code to control time between events. For this, first have a variable to store the object of the class Time_Control, for example, var control:Time_Control = Time_Control(0). After that, each time you want to control the time of something just do the following:

func send_message(){
    if control.can_send{
        //Start the time controller with 60 seconds
        control = Time_Control(60)
        control.start()

        //Let the user send message
        //... your code
    }else{
        //Don't let the user send message
        //...
    }
}

When the user interacts with your UI, you can call the function send_message(). It will allow the user to send a message every 60 seconds.

In Swift you can get the Unix timestamp of the current moment using:

let currentUnixTimestamp = Date().timeIntervalSince1970

Unix time simply counts the seconds that have elapsed since 1 Jan, 1970 00:00:00 UTC. See Wikipedia to learn more.

Using this, you could create a field in which you save the current timestamp every time a comment is sent and then check the current time against the saved timestamp. If your viewModel is of a class type, which I assume it is, it is the perfect place to put this code. It might look like this:

class ViewModel {
    // How many seconds to wait before the user can comment again
    private static let cooldownInSeconds = 60

    private var lastSendTimestamp: Int? = nil


    func sendComment(nickname: String, body: String) {
        let currentTime = Date().timeIntervalSince1970

        if currentTime >= (lastSendTimestamp ?? Int.min) + ViewModel.cooldownInSeconds {
            lastSendTimestamp = currentTime
            
            // Send comment here
        } else {
            // Cannot send comment because cooldown has not run out
        }
    }
}

Note that putting the variable in structs (like your View) will not work well, due to their immutable nature.

Related