在 Swift 中使用 Timer 不断调用 api 请求

Posted

技术标签:

【中文标题】在 Swift 中使用 Timer 不断调用 api 请求【英文标题】:use Timer to call the api request constantly in Swift 【发布时间】:2021-11-25 10:06:33 【问题描述】:

我想进行 API 请求调用,直到获得特定值。

这可能是超级基本的东西,但我是一名初级程序员,所以仍然需要一些建议。

函数checkIsReady会返回布尔值,开始时返回false,过一会儿返回true。

struct IsReady: Codable 
    let isReady: Bool



func checkIsReady(id: String, completion: @escaping (Bool) -> Void) 
    
    var isReady: Bool = false
    
    AF.request("\(myendpoint)")
        .validate()
        .responseJSON  response in
            guard let data = response.data else  return 
            
            let decoder: JSONDecoder = JSONDecoder()
            var result: IsReady?
            
            do 
                result = try decoder.decode(IsReady.self, from: data)
             catch 
                print("error with get stream ready status: \(error)")
            
            
            if result?.isReady 
                isReady = true
            
            
            DispatchQueue.main.async 
                completion(isReady)
            
        

所以我知道上面的函数一开始返回 false 并且需要一些时间才能返回 true,我想创建一个计时器每 5 秒调用一次函数,直到我得到真实的值。

然后我写了下面的代码。

private var timer = Timer()
private let currentRetryCount = 0
private var isReady = false
private let myId = "AAA"

func apiCallTest() 
    if currentRetryCount > 9 && timer.isValid 
        timer.invalidate()
    
        
    if !isReady && !timer.isValid 
            checkIsReady(id: myId)  [weak self] ready in
                if !ready 
                    timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block:  _ in
                        checkIsReady(id: myId) // what should I do for the completion?
                    )
                
            
        

问题是当我在 apiCallTest 函数的完成中准备好为 false 时,我想创建一个计时器来每 5 秒调用一次 checkIsReady (timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true,...),但不确定在完成块中写入什么下一次调用 checkIsReady 函数(我写的那个 what should I do for the completion?)。我想知道其他人如何解决这种每 5 秒调用一次 API 的问题。顺便说一句,如果我在完成块中写 nil,它会给我一个错误。

【问题讨论】:

如果我没记错的话,在完成块中创建一个永久循环并每 5 秒重新创建一个补充的计时器。最后,您将运行大量计时器。在 AF.request 的完成处理程序中,您只需要休眠 5 秒,然后再次调用 AF.request。如果没有必要,不要忘记当 isReady 为 True 时不要重新启动。 【参考方案1】:

这就是我的做法。

我们进行初始调用,如果失败,它会启动一个计时器,调用 apiCallTest() 第二个和后续请求,直到达到限制尝试次数。

这个

var currentRetryCount = 0
var isReady = false
let myId = "AAA"
var timer: Timer? = nil

func apiCallTest() 
    checkIsReady(id: myId) 
        if $0 == true 
            self.timer?.invalidate()
            self.isReady = true;
         else 
            self.currentRetryCount = self.currentRetryCount + 1
            if currentRetryCount > 9 
                self.timer.invalidate()
            
        
    

然后是你打第一个电话的地方

checkIsReady(id: myId, completion: 
    if $0 == true 
        self.isReady = true // if the first attempt returns true no further action required
     else 
        // if it fails we increment the count and start the timer
        self.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block:  _ in apiCallTest() )
        self.currentRetryCount = self.currentRetryCount + 1
    
)

函数apiCallTest() 将回答所有后续尝试

【讨论】:

以上是关于在 Swift 中使用 Timer 不断调用 api 请求的主要内容,如果未能解决你的问题,请参考以下文章

Timer.scheduledTimer 在 Swift 3 中不起作用

以 NSException Timer Swift Crash 类型的未捕获异常终止

swift中定时器(Timer) 的使用

为啥我在 Swift 中的初始化程序不断收到“调用中的额外参数”

如何在Swift上计算Timer

Swift HealthKit UpdateQuery 只被调用一次