Search code examples
iosjsonswifttableviewalamofire

How to fill table with JSON data in Swift 3?


I created a tableView in which I want to put news using this link

   https://api.sis.kemoke.net/news

There are three things which I want to get and populate the table.

    String title
    String text
    String link

Here is my class

    import Alamofire //Framework for handling http requests
    import UIKit

/A class which will process http requests, receive the news as string and fill the array with such data which will be displayed in a table/ class NewsTableViewController: UITableViewController {

//Array which holds the news
var newsData:Array< String > = Array < String >()

// Download the news
func downloadData() {
    Alamofire.request("https://api.sis.kemoke.net/news").responseJSON { response in
        print(response.request)  // original URL request
        print(response.response) // HTTP URL response
        print(response.data)     // server data
        print(response.result)   // result of response serialization

        //Optional binding to handle exceptions
        if let JSON = response.result.value {
            print("JSON: \(JSON)")
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    downloadData()
    extractData()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

// MARK: - Table view data source
// Number of sections i table vie
override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

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


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = newsData[indexPath.row]
    return cell
}

// Extract the data from the JSON
func extractData() {
    Alamofire.request("https://api.sis.kemoke.net/news").responseJSON { response in
        debugPrint(response)

        if let json = response.result.value {
            print("JSON: \(json)")
            self.newsData = json as! Array
        }
    }
}

// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}

}

Later-on I will try to get the image as well but for now those three variables should be enough.


Solution

    • First of all create a custom struct for the data

      struct News {
        let title : String
        let text : String
        let link : String
      
        init(dictionary: [String:String]) {
           self.title = dictionary["title"] ?? ""
           self.text = dictionary["text"] ?? ""
           self.link = dictionary["link"] ?? ""
        }
      }
      
    • The data source array is

      var newsData = [News]() 
      
    • Use only downloadData(), delete the other method.
      Using a custom struct the parsing is quite simple:

      func downloadData() {
          Alamofire.request("https://api.sis.kemoke.net/news").responseJSON { response in
              print(response.request)  // original URL request
              print(response.response) // HTTP URL response
              print(response.data)     // server data
              print(response.result)   // result of response serialization
      
              //Optional binding to handle exceptions
              if let json = response.result.value as? [[String:String]] {
                  self.newsData = json.map{ News(dictionary: $0) }
                  self.tableView.reloadData()
              }
          }
      }
      
    • In cellForRow... display the title

      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
          let news = newsData[indexPath.row]
          cell.textLabel?.text = news.title
          return cell
      }