在 Swift 中节流而不进行反应
Posted
技术标签:
【中文标题】在 Swift 中节流而不进行反应【英文标题】:Throttling in Swift without going reactive 【发布时间】:2017-04-10 12:04:15 【问题描述】:有没有一种简单的方法可以在响应式编程中实现 Throttle 功能,而无需使用 RxSwift 或类似框架。
我有一个 textField 委托方法,我不想在每次插入/删除字符时触发它。
如何使用 vanilla Foundation 做到这一点?
【问题讨论】:
代理每次都会触发。在您的委托方法中,您可以启动一个计时器。如果委托在计时器关闭之前再次触发,请重新启动计时器。当计时器响起时,做任何你需要做的事情。 【参考方案1】:是的,有可能实现。
但首先让我们回答一个小问题,什么是节流?
在软件、节流过程或节流控制器中 有时称为,是负责调节速率的过程 执行哪个应用程序处理,无论是静态的还是 动态的。
Swift 中Throttling 函数的示例。
如果您使用委托方法进行描述,您将遇到每次都会调用委托方法的问题。所以我会写一个简短的例子,在你描述的情况下是怎么做到的。
class ViewController: UIViewController
var timer: Timer?
@IBOutlet weak var textField: UITextField!
override func viewDidLoad()
super.viewDidLoad()
textField.delegate = self
@objc func validate()
print("Validate is called")
extension ViewController: UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.validate), userInfo: nil, repeats: false);
return true
【讨论】:
timer?.invalidate()
简单一点。
我认为现在就可以了。仅使用计时器的问题是:每个新计时器都会执行选择器而不取消之前的调用。这将打败整个观点。并且无法保证对选择器的调用按照假定的顺序进行。
@Carpsen90 您实际上并不需要它们按特定顺序排列。您只需要忽略所有先前的结果。这应该如何完成取决于您的 API。我通常会在请求中传递一些上下文以及上下文中的文本。请求完成后,我可以比较当前文本是否与我们请求的文本相同。
换句话说,选择器应该是可取消的。我去看看。
这不是去抖功能吗?油门功能,不会总是从最后一个 textField 输入触发0.5
。相反,无论用户是否输入了新字符,它总是会在0.5
触发。【参考方案2】:
免责声明:我是一名作家。
Throttler 可以成为让你开心的正确武士刀。
您可以在不使用 Throttler 之类的反应式编程的情况下进行去抖动和节流,
import Throttler
// advanced debounce, running a first task immediately before initiating debounce.
for i in 1...1000
Throttler.debounce
print("debounce! > \(i)")
// debounce! > 1
// debounce! > 1000
// equivalent to debounce of Combine, RxSwift.
for i in 1...1000
Throttler.debounce(shouldRunImmediately: false)
print("debounce! > \(i)")
// debounce! > 1000
Throttler 还可以进行高级去抖动,在启动去抖动之前立即运行第一个事件,Combine 和 RxSwift 默认没有。
您可以,但您可能需要自己进行复杂的实现。
【讨论】:
以上是关于在 Swift 中节流而不进行反应的主要内容,如果未能解决你的问题,请参考以下文章