簡體   English   中英

使用SwiftyJSON和Alamofire在TableView上顯示JSON數據

[英]Showing JSON data on TableView using SwiftyJSON and Alamofire

我想在Table View上顯示從服務器獲取的JSON數據。 問題是,我無法讓它顯示出來。 我嘗試了幾種不同的方法並經過大量搜索以找到解決方案,但我做不到。

我的代碼(全部)如下所示,我希望有人可以幫助我。 提前致謝。

import UIKit
import Alamofire
import SwiftyJSON

class MasterViewController: UITableViewController {

var tableTitle = [String]()
var tableBody = [String]()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    getJSON()

}

func getJSON(){

    Alamofire.request(.GET, "http://announcement.vassy.net/api/AnnouncementAPI/Get/").responseJSON { (Response) -> Void in

        // checking if result has value
        if let value = Response.result.value {

            let json = JSON(value)

            for anItem in json.array! {

                let title: String? = anItem["Title"].stringValue
                let body: String? = anItem["Body"].stringValue
                self.tableTitle.append(title!)
                self.tableBody.append(body!)

            }

        }

    }

    self.tableView.reloadData()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// Table View Stuff

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.tableTitle.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TableViewCell

    // cell config
    cell.title!.text = tableTitle[indexPath.row]
    cell.body!.text = tableBody[indexPath.row]
    return cell

}

}

該Alamofire網絡請求是異步的,這意味着你可以不知道什么時候 ,結果會回來的。

這里的問題是你在Alamofire請求的范圍之外重新加載tableView,所以它在數據返回之前執行。

重新加載應該在相同的范圍內,並在主線程上,例如:

func getJSON(){

    Alamofire.request(.GET, "http://announcement.vassy.net/api/AnnouncementAPI/Get/").responseJSON { (Response) -> Void in

        // checking if result has value
        if let value = Response.result.value {

            let json = JSON(value)

            for anItem in json.array! {

                let title: String? = anItem["Title"].stringValue
                let body: String? = anItem["Body"].stringValue
                self.tableTitle.append(title!)
                self.tableBody.append(body!)

            }

            dispatch_async(dispatch_get_main_queue()) {
                self.tableView.reloadData()             
            }

        }

    }

}

我認為@Eric在他的回答中幾乎說了一切,然而,不是它在設計中做出了很好的決定,保持代碼在同一個UITableViewController制作網絡請求,這樣就可以保留兩個獨立的東西,並因不同的原因而改變。

我的建議是將代碼的兩個部分分開,從而解耦兩個層之間的依賴關系。 這樣,當您需要更改與網絡請求處理程序相關的任何內容時,您無需在發出相同請求的任何地方更改它,這是一個建議!

如果你想這樣做,你可以使用閉包來處理Alamofire passgin的異步行為,你在處理網絡請求的包裝器中的completionHandler ,例如,讓我們使用單例模式定義一個簡單的包裝器(它僅用於解釋樣本的目的,你可以根據需要處理它)。

import AlamofireImage
import SwiftyJSON

class NetworkHandler { 

   /// The shared instance to define the singleton.
  static let sharedInstance = RequestManager()


  /**
  Private initializer to create the singleton instance.
  */
  private init() { }

  func getJSON(completionHandler: (json: JSON?, error: NSError?) -> Void) {

      Alamofire.request(.GET, http://announcement.vassy.net/api/AnnouncementAPI/Get/).responseJSON { response in

        switch(response.result) {
        case .Success(let value):

            let json = JSON(value)
            completionHandler(json: json, error: nil)

        case .Failure(let error):
            completionHandler(json: nil, error: error)
        }
    }
  }
}

然后在你的UITableViewController你可以用這種方式調用Alamofire的新包裝器:

class MasterViewController: UITableViewController {

   var tableTitle = [String]()
   var tableBody = [String]()

   override func viewDidLoad() {
       super.viewDidLoad()
       // Do any additional setup after loading the view, typically from a nib.

       NetworkHandler.sharedInstance.getJSON { [weak self] (json, error) -> Void in

         // request was made successful
         if error == nil {
            for anItem in json.array! {
               let title: String? = anItem["Title"].stringValue
               let body: String? = anItem["Body"].stringValue
               self.tableTitle.append(title!)
               self.tableBody.append(body!)
            }

            dispatch_async(dispatch_get_main_queue()) {
                self.tableView.reloadData()             
            }
         }
       }
    }

    // rest of your code
 }

以上述方式保持代碼解耦,這是一個很好的設計。

我希望這對你有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM