如何等待给定时间并仅执行最后一个函数调用 [英] How to wait for a given time and only perform last function call

查看:64
本文介绍了如何等待给定时间并仅执行最后一个函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一个名为Person的类,其中包含诸如firstNamelastName的变量.我正在使用reactCocoa框架来监听这些变量的变化,但可以说我仅使用内置的KVO侦听,例如didSet{}.因此,假设我有以下代码:

Let's say I have a class named Person, with variables like firstName and lastName. I am listening to changes in these variables using a reactiveCocoa-framework, but let's say I'm only using the built in KVO-listening, like the didSet{}. So assume I have this code:

let firstName:String { didSet{ self.nameDidChange() }}
let lastName: String { didSet{ self.nameDidChange() }}

func nameDidChange(){ print("New name:", firstName, lastName}

每次我更改名字或姓氏时,它都会自动调用函数nameDidChange. 我想知道的是,在我同时更改firstNamelastName时,是否有任何明智的举动可以防止nameDidChange函数连续两次被调用.

Every time I'd change either the first name or the last name, it would automatically call the function nameDidChange. What I'm wondering, is if there's any smart move here to prevent the nameDidChange function from being called twice in a row when I change both the firstName and the lastName.

假设firstName中的值是"Anders",而lastName中的值是"Andersson",那么我运行以下代码:

Let's say the value in firstName is "Anders" and lastName is "Andersson", then I run this code:

firstName = "Borat"
lastName = "Boratsson"

nameDidChange在这里将被调用两次.它将首先打印出"New name: Borat Andersson",然后打印出"New name: Borat Boratsson".

nameDidChange will be called twice here. It will first print out "New name: Borat Andersson", then "New name: Borat Boratsson".

简单的说,我想创建一个名为nameIsChanging()之类的函数,每当调用didSet中的任何一个时都调用它,并启动计时器0.1秒,然后 调用nameDidChange(),但是这两个didSet也会调用nameIsChanging,因此计时器将运行两次,并两次触发.为了解决这个问题,我可以保留一个全局" Timer,并使它自己失效并重新启动计数或类似的操作,但是我对解决方案的思考越多,得到的结果就越难看.这里有最佳做法"吗?

In my simple mind, I'm thinking I can create a function called something like nameIsChanging(), call it whenever any of the didSet is called, and start a timer for like 0.1 second, and then call nameDidChange(), but both of these didSets will also call nameIsChanging, so the timer will go twice, and fire both times. To solve this, I could keep a "global" Timer, and make it invalidate itself and restart the count or something like that, but the more I think of solutions, the uglier they get. Are there any "best practices" here?

推荐答案

我认为您的做法正确.我认为您只需要延迟对名称更改的呼叫,直到用户键入"Stopped"为止.

I think you are on the right track. I think you just need to delay the call to name changed until the user has "Stopped" typing.

类似这样的东西:

var timer = Timer()

var firstName: String = "Clint" {
    didSet {
        timer.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: { _ in
            self.nameDidChange()
        })
    }
}

var secondName: String = "Eastwood" {
    didSet {
        timer.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: { _ in
            self.nameDidChange()
        })
    }
}

func nameDidChange() {
    print(firstName + secondName)
}

每次更改名字或名字时,它将停止计时器,并等待另外0.2秒,直到提交名称更改.

Everytime the first or second name is changed it will stop the timer and wait another 0.2 seconds until it commits the name change.

修改

在阅读了亚当·冯特雷拉(Adam Venturella)的评论后,我意识到这确实是一种反跳技术.如果您想了解更多有关此概念的信息,对Google有用.

After reading the comment by Adam Venturella I realized that it is indeed a debouncing technique. It would be useful to google the concept if you would like to learn some more about it.

这里是一个说明概念的简单游乐场:

Here is a simple Playground that illustrates the concept:

import UIKit
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

var timer: Timer? = nil

func nameDidChange() {
    print("changed")
}

func debounce(seconds: TimeInterval, function: @escaping () -> Swift.Void ) {
    timer?.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: seconds, repeats: false, block: { _ in
        function()
    })
}

debounce(seconds: 0.2) { nameDidChange() }
debounce(seconds: 0.2) { nameDidChange() }
debounce(seconds: 0.2) { nameDidChange() }
debounce(seconds: 0.2) { nameDidChange() }
debounce(seconds: 0.2) { nameDidChange() }
debounce(seconds: 0.2) { nameDidChange() }

输出:

changed

nameDidChange函数仅执行一次.

The nameDidChange function was executed only once.

这篇关于如何等待给定时间并仅执行最后一个函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆