Showing JSON data on TableView using SwiftyJSON and Alamofire

守給你的承諾、 提交于 2019-12-05 10:40:51

The Alamofire network request is asynchronous, meaning you can't know when the result will come back.

The problem here is that you reload the tableView outside the scope of the Alamofire request, so it is executed before the data comes back.

The reload should happen in the same scope, and on the main thread, for example:

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()             
            }

        }

    }

}

I think @Eric said almost everything in his answer, nevertheless, not it's a good decision in design keep the code for make the network request in your same UITableViewController this keep a couple between two things that are independents and change for differents reasons.

My advice is separate the two parts of the code decoupling the dependency between your two layers. In this way when you need to change anything related with your networking request handler you don't need to change it in any place where you make the same request, it's an advice!!!.

In case you want to do it, you can use closures to hanlde the async behaviour of Alamofire passgin the completionHandlerinside the wrapper you make to handle the networking requests, for example, let's define a simple wrapper using the singleton pattern (it's just for the purpose of explain the sample, you can handle it as you want).

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)
        }
    }
  }
}

Then in your UITableViewController you can call the new wrapper to Alamofire in this way:

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
 }

In the above way you keep the code decoupled, it's a good design.

I hope this help you

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!