Swift3 如何在Swift 3中的每一步使用Alamofire执行顺序请求并更新progressHUD
好吧,我为这件事发疯了 我使用的是Alamofire4.x(Swift 3和XCode 8.1)。我需要从一个需要身份验证的站点获取和解析几个html请求(不幸的是,没有JSONAPI)。然后用Fuzi解析HTML,这个过程可能需要一些时间,所以我计划使用ProgressHUD(确切地说是PKHUD)让用户知道正在发生什么。我还需要获取一些不在身份验证后面的html 我创建了一个结构和函数来处理整个网络过程并解析数据 我设法执行了请求并获取了所需的数据,但我似乎不知道如何在正确的时间更新HUD 以下是我目前的代码:Swift3 如何在Swift 3中的每一步使用Alamofire执行顺序请求并更新progressHUD,swift3,grand-central-dispatch,alamofire,xcode8.1,Swift3,Grand Central Dispatch,Alamofire,Xcode8.1,好吧,我为这件事发疯了 我使用的是Alamofire4.x(Swift 3和XCode 8.1)。我需要从一个需要身份验证的站点获取和解析几个html请求(不幸的是,没有JSONAPI)。然后用Fuzi解析HTML,这个过程可能需要一些时间,所以我计划使用ProgressHUD(确切地说是PKHUD)让用户知道正在发生什么。我还需要获取一些不在身份验证后面的html 我创建了一个结构和函数来处理整个网络过程并解析数据 我设法执行了请求并获取了所需的数据,但我似乎不知道如何在正确的时间更新HUD
import Alamofire
import Fuzi
import PKHUD
struct MyMSCProvider {
static let baseUrl = "http://mastersswimming.ca"
//I tried with or without a custom queue - same result
static let processingQueue = DispatchQueue(label: "com.colddiver.processing-queue", qos: .utility)
static func fetchData(data: MscRequest) {
if data.profile || data.log {
//Authenticate first!
HUD.show(.labeledProgress(title: "Authenticating", subtitle: ""))
let requestUrl = "\(baseUrl)/MyMscPage.jsp"
let parameters = ["locale": "en", "username": data.user.username, "password": data.user.password]
Alamofire.request(requestUrl, method: .post, parameters: parameters).responseData(
queue: processingQueue,
completionHandler:
{ response in
// Now on the processingQueue you created earlier.
print("THREAD: \(Thread.current) is main thread: \(Thread.isMainThread)")
switch response.result {
case .success:
if data.profile {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Profile", subtitle: ""))
}
let userProfile = parseProfile(data: response.data!, user: data.user)
print(userProfile)
}
if data.log {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Log", subtitle: ""))
}
fetchLog()
}
if data.records {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Records", subtitle: ""))
}
fetchRecords(recordsToFetch: data.recordsToFetch)
}
if data.times {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Times", subtitle: ""))
}
print("Fetching times is not implemented yet")
}
DispatchQueue.main.async {
HUD.flash(.success)
}
case .failure(let error):
HUD.flash(.error)
print("Alamofire request failed")
print(error)
}
}
)
} else {
//Just fetch - no need to authenticate first
if data.records {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Records", subtitle: ""))
}
fetchRecords(recordsToFetch: data.recordsToFetch)
}
if data.times {
print("Fetching times is not implemented yet")
}
DispatchQueue.main.async {
HUD.flash(.success)
}
}
}
static func fetchRecords(recordsToFetch: RecordsToFetch) {
for province in recordsToFetch.provinces {
for ageGroup in recordsToFetch.ageGroups {
for gender in recordsToFetch.genders {
DispatchQueue.main.async {
HUD.show(.labeledProgress(title: "Getting Records", subtitle: "\(province) - \(gender+Helpers.getAgeGroupFromAge(age: Int(ageGroup)!))"))
}
let requestUrl = "\(baseUrl)/Records.jsp"
let parameters = ["locale": "en", "province": province, "age": ageGroup, "gender": gender, "course": "*"]
Alamofire.request(requestUrl, method: .post, parameters: parameters).responseData(
queue: processingQueue,
completionHandler: { response in
switch response.result {
case .success:
let recordArray = parseRecords(data: response.data!, province: province, ageGroup: ageGroup, gender: gender)
case .failure(let error):
DispatchQueue.main.async {
HUD.flash(.failure)
}
print("Alamofire request failed")
print(error)
}
}
)
}
}
}
}
static func fetchLog() {
let requestUrl = "\(baseUrl)/ViewLog.jsp"
Alamofire.request(requestUrl).responseData(
queue: processingQueue,
completionHandler: { response in
switch response.result {
case .success:
let log = parseLog(data: response.data!)
case .failure(let error):
DispatchQueue.main.async {
HUD.flash(.failure)
}
print("Alamofire request failed")
}
}
)
}
// MARK: - Convenience structs
struct MscRequest {
let profile: Bool
let log: Bool
let times: Bool
let records: Bool
let recordsToFetch: RecordsToFetch
let user: MscUser
let parentView: UITableViewController
}
在此设置下,我将在TableViewController中设置MscRequest,并启动一系列a请求,如下所示:
let myData = MscRequest.init(
profile: true,
log: true,
times: false,
records: true,
recordsToFetch: RecordsToFetch.init(
provinces: ["NB", "CA"],
ageGroups: ["20", "25", "30", "35", "40"],
genders: ["M", "F"]),
user: MscUser.init(
username: "SomeUserName",
password: "SomePassword"),
parentView: self
)
MyMSCProvider.fetchData(data: myData)
通过此设置,所有HUD更新都会同时完成(在主线程上),并在后台获取和解析仍在进行时终止。不完全是我想要的
我尝试了各种迭代(有或没有自定义队列),我也直接从Alamofire的手册中尝试了HTML请求代码(省略了completionHandler部分),但仍然得到了相同的结果
我也看过GrandCentralDispatch教程(比如这篇:),但我还没有弄明白如何在使用Alamofire时应用信息
值得注意的是,我在Objective-C中通过手动请求实现了这一点。我正在将这个旧的应用程序升级到Swift 3,我想我应该试试Alamofire
我忍不住觉得我错过了一些明显的东西。。。有什么建议吗 您必须使用DownloadRequest和progress 再看看这篇文章,它解释道:
好的,我找到了一种使用DispatchGroup(Swift 3,Alamofire 4.x)做我想做的事情的方法
哼。。。我不想显示下载进度。我想在每个新请求开始时更新hud,让用户知道正在下载的内容。单个请求非常快,html解析可能需要一些时间…好的,这个()非常接近我认为需要的内容,但我还没有弄清楚如何使其工作…看起来这个()可能也有帮助-如果没有,也许PromiseKit。。。
func fetchData() {
let requestGroup = DispatchGroup()
//Need as many of these statements as you have Alamofire.requests
requestGroup.enter()
requestGroup.enter()
requestGroup.enter()
Alamofire.request("http://httpbin.org/get").responseData { response in
print("DEBUG: FIRST Request")
requestGroup.leave()
}
Alamofire.request("http://httpbin.org/get").responseData { response in
print("DEBUG: SECOND Request")
requestGroup.leave()
}
Alamofire.request("http://httpbin.org/get").responseData { response in
print("DEBUG: THIRD Request")
requestGroup.leave()
}
//This only gets executed once all the above are done
requestGroup.notify(queue: DispatchQueue.main, execute: {
// Hide HUD, refresh data, etc.
print("DEBUG: all Done")
})
}