2016-11-11 60 views
0

好每一步更新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。

不禁讓我感覺我失去了一些明顯的東西......任何提示?

+0

好的,這(http://stackoverflow.com/questions/36911192/how-to-load-view-after-alamofire-finished-its-job)是更接近我認爲我需要,但我沒有'噸想出如何使它的工作尚未... –

+0

看起來像這樣(http://stackoverflow.com/questions/28634995/cha in-multiple-alamofire-requests)也可能有幫助 - 如果不是PromiseKit ... –

回答

2

好吧,我找到了一種方法做我想要使用DispatchGroup(SWIFT 3,Alamofire 4.x版)

什麼
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") 
    }) 

} 
0

你必須使用DownloadRequest並使用進度。

也看看這篇文章,解釋說:

Alamofire POST request with progress

+0

Humm ...我不想顯示下載進度。我想在每個新請求開始時更新hud,讓用戶知道正在下載什麼。個別請求速度相當快,這是可能需要一段時間的HTML解析... –