带循环的Alamofire同步请求

时间:2017-06-09 13:02:23

标签: json swift request alamofire

我知道如何使用完成进行同步请求。但我不知道如何在循环中发出同步请求。

这是我的代码:

    var marks = [JSON]()
    let vnCount = studentVnCodes.count

    var i: Int = 0

    marks = [JSON](repeating: JSON.null, count: vnCount)

    for vn in studentVnCodes {
        let url = "https://example.com/Student/Grade/GetFinalGrades?&vn=\(vn)&academic_year=All"

        Alamofire.request(url).responseString { response in

            var dataString: String = (response.result.value)!

            dataString = cleanMarksJSON(string: dataString)

            if let dict = convertToDictionary(text: dataString) {

                marks[i] = (JSON(dict as Any))

                i += 1

                if (vnCount == marks.count) {
                    completionHandler(marks)
                }
            }

        }
    }

我尝试使用vn代码(vnCount)进行x请求。 问题是我在JSON marks数组中以错误的顺序获取所有JSON。当然,因为它在数组完成时会在数组中附加响应,并且不会等待先前的请求结束。

所以我尝试创建一个变量i来强制函数以正确的顺序附加响应。这不起作用。任何的想法?谢谢!

1 个答案:

答案 0 :(得分:1)

您可以在串行队列中按顺序运行请求,在这种情况下,它们将按您调用它们的顺序执行,这可确保它们按顺序添加到阵列中。但是,这似乎是一个次优的解决方案,因为您通过顺序而不是同时运行请求来减少执行时间。

如果您仍想像这样实现它,请参阅以下代码:

var marks = [JSON]()
let vnCount = studentVnCodes.count
marks = [JSON](repeating: JSON.null, count: vnCount)
let serialQueue = DispatchQueue(label: "serialQueue")
for vn in studentVnCodes {
    serialQueue.async{
        let url = "https://example.com/Student/Grade/GetFinalGrades?&vn=\(vn)&academic_year=All"
        Alamofire.request(url).responseString { response in
            var dataString: String = (response.result.value)!
            dataString = cleanMarksJSON(string: dataString)
            if let dict = convertToDictionary(text: dataString) {
                marks.append(JSON(dict as Any))
                if (vnCount == marks.count) {
                    completionHandler(marks)
                }
            }
        }
    }
}

更好的解决方案是将响应存储在数据结构中,其中排序并不重要,例如在字典中,您的键是索引(您将用于数组)和您的值是JSON响应值。这样,您可以同时运行请求并按顺序访问响应。