如何使异步请求Swift 5的for循环停止

Posted

技术标签:

【中文标题】如何使异步请求Swift 5的for循环停止【英文标题】:How to make the for loop stop for the asynchronous request Swift 5 【发布时间】:2020-03-11 17:46:32 【问题描述】:

这是我希望 for 循环等待 func getVenueDetails 完成的 func,如果完成为 true,则跳出循环,如果不是,则继续下一个场地 ID。

    func searchVenues(lat: Double, lng: Double) 
    let parameter: [String: String] = [
        "ll": "\(lat),\(lng)",
        "radius": "600",
        "limit": "10",
        "intent": "browse",
        "categoryId": "4bf58dd8d48988d1e4931735,4bf58dd8d48988d1f1931735,4deefb944765f83613cdba6e,4bf58dd8d48988d17f941735,52e81612bcbc57f1066b79eb,4bf58dd8d48988d181941735,4bf58dd8d48988d1f4931735,4bf58dd8d48988d189941735,4bf58dd8d48988d182941735,4bf58dd8d48988d17b941735,4bf58dd8d48988d163941735,4bf58dd8d48988d164941735,4bf58dd8d48988d165941735,56aa371be4b08b9a8d57356a,4bf58dd8d48988d12f941735"
    ];

    var isSent2: Bool = false


    client.request(path: "venues/search", parameter: parameter)  result in
        switch result 
        case let .success(data):

            let jsonResponse = try! JSONSerialization.jsonObject(with: data, options: [])
            let json = JSON(jsonResponse)

             let name = json["response"]["venues"][0]["name"].string
                print("NAME FROM JSON: ", name)

                let id = json["response"]["venues"][0]["id"].string
                print("id of foursquare", id)

            let group = DispatchGroup()

            group.notify(queue: .main) 


            for (key,subJson):(String, JSON) in json["response"]["venues"] 
               //group.enter()
                let placeName = subJson["name"].string
                print("place name:",placeName.unsafelyUnwrapped)

                let placeId = subJson["id"].string
                print("place id:",placeId.unsafelyUnwrapped)

                    group.enter()

                    self.getVenueDetails(id: placeId!)  (isSent) in

                        print("isSent", isSent)
                        isSent2 = isSent

                        group.leave()

                    

               if (isSent2)
                      print("linaaa")
                //group.leave()
                break

                

            //end of for loop

            
        //  print("json == ", jsonResponse)
        case let .failure(error):
            // Error handling
            switch error 
            case let .connectionError(connectionError):
                print(connectionError)
            case let .responseParseError(responseParseError):
                print(responseParseError)   // e.g. JSON text did not start with array or object and option to allow fragments not set.
            case let .apiError(apiError):
                print(apiError.errorType)   // e.g. endpoint_error
                print(apiError.errorDetail) // e.g. The requested path does not exist.
            
        
    


这里是另一个函数,请求场地详细信息,所以我希望当 isSent 返回 true 时 searchVenues 中的 for 循环停止(中断),如果返回 false 则继续下一个。

func getVenueDetails(id: String, completionHandler: @escaping (Bool)->Void) 

    var isSent: Bool = false


    let parameter: [String: String] = [
        "VENUE_ID": "\(id)",

    ];

    client.request(path: "venues/\(id)", parameter: parameter)  result in

        switch result 
        case let .success(data):

            let jsonResponse = try! JSONSerialization.jsonObject(with: data, options: [])

            let json = JSON(jsonResponse)
            // print("json == ", jsonResponse)

            let name = json["response"]["venue"]["name"].string

            if let rating:Double = json["response"]["venue"]["rating"].double 
                print("rating from: ", rating)
                //rat = rating

                if (rating > 2)  
                    self.foursquareNotification(name: name!)
                    print("here inside lol")
                    isSent = true
                    DispatchQueue.main.async 


                    completionHandler(isSent)
                    print("isSent hereee", isSent)

                    
                 //end if
                else 
                    isSent = false
                    DispatchQueue.main.async 


                    completionHandler(isSent)
                    
                //end else
             //end if rating

            //                rat = json["response"]["venue"]["rating"].double!
            //                print("rating from: ", rat)
            //                //rat = rating.unsafelyUnwrapped

        case let .failure(error):
            // Error handling
            switch error 
            case let .connectionError(connectionError):
                print(connectionError)
            case let .responseParseError(responseParseError):
                print(responseParseError)   // e.g. JSON text did not start with array or object and option to allow fragments not set.
            case let .apiError(apiError):
                print(apiError.errorType)   // e.g. endpoint_error
                print(apiError.errorDetail) // e.g. The requested path does not exist.
            
        
    
    //return isSent
//end getVenueDetails

【问题讨论】:

我的意思是等待异步请求完成并返回然后继续下一次迭代 【参考方案1】:

你需要去掉for循环

var res =  json["response"]["venues"] 

然后

var current = 0
func start(item:ItemType) 
    let placeName = subJson["name"].string 
    let placeId = subJson["id"].string
     self.getVenueDetails(id: placeId!)  (isSent) in 
        if isSent 
            counter += 1
            start(nextItem)
     

【讨论】:

ItemType 是什么意思?什么是 nextItem、counter 和 current?你能解释一下吗?谢谢!

以上是关于如何使异步请求Swift 5的for循环停止的主要内容,如果未能解决你的问题,请参考以下文章

js中for循环里面有异步请求怎么解决

使用 DispatchGroup、DispatchQueue 和 DispatchSemaphore 按顺序执行带有 for 循环的 Swift 4 异步调用

如何获取异步请求的数据?

解决for循环中异步请求顺序不一致的问题

NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解决,这样我们就不会收到 EMFILE 错误?

Node.js如何将数组索引传递给异步函数