好每一步更新progressHUD,我要瘋了這一個...如何使用Alamofire執行順序請求,並在斯威夫特3
我使用Alamofire 4.x版(斯威夫特3和8.1的XCode )。我需要從需要身份驗證的站點獲取並解析幾個html請求(不幸的是,沒有json API)。然後用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
}
在此設置中,我會建立一個MscRequest在TableViewController並推出了一系列像這樣一個請求:
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的手冊(省略completionHandler部分)的HTML請求代碼,但我仍然得到同樣的結果...
我也看了一下大中央調度教程(比如這個:http://www.appcoda.com/grand-central-dispatch/),但我還沒有想出如何使用Alamofire何時應用信息...
值得注意的,我設法在Objective-C中使用手動NSURLRequests來完成這項工作。我正在將這個舊的應用程序升級到Swift 3,並認爲我應該試試Alamofire。
不禁讓我感覺我失去了一些明顯的東西......任何提示?
好的,這(http://stackoverflow.com/questions/36911192/how-to-load-view-after-alamofire-finished-its-job)是更接近我認爲我需要,但我沒有'噸想出如何使它的工作尚未... –
看起來像這樣(http://stackoverflow.com/questions/28634995/cha in-multiple-alamofire-requests)也可能有幫助 - 如果不是PromiseKit ... –