Search code examples
jsonswiftapiuitableviewviewcontroller

Get data from API call and show another viewController on UItableView row click


I'm new to Swift, so I ask for help. I show list of characters on tableview using API call.When user click one row, I want to call API ,get data and show it in new viewController
API call url looks like :

https://rickandmortyapi.com/api/character/{user_clicked_row_charactor_id}

Sample response for id = 3

{
"id": 3,
"name": "Summer Smith",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Female",
}

And so it is necessary for each of the characters. Tell or direct how to implement this?

Sorry for my bad English. My code:

class UsersTableViewController: UITableViewController {



    var characters = [Results]()



     override func viewDidLoad() {
         super.viewDidLoad()

        LoadCharacters()

    }
    func LoadCharacters() {
        let urlString = "https://rickandmortyapi.com/api/character/"


        if let url = URL(string: urlString)
        {
            let session = URLSession(configuration: .default)

            let task = session.dataTask(with: url) { (data, responce, error) in
            if error != nil {
                       print(error!)
                       return
            }

                if let safeData = data {
                    self.parseJson(usersData: safeData)

                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                }
            }

            task.resume()
            self.tableView.reloadData()
        }
    }

    func parseJson(usersData: Data) {
        let decoder = JSONDecoder()
        do {


            let decodedData = try decoder.decode(JSONData.self, from: usersData)
            characters = decodedData.results
            print(decodedData.results[0].name)
        } catch {
            print(error)
        }
        }







     struct JSONData: Decodable {
         let results: [Results]
     }
     struct Results: Decodable {
         let name: String

     }

     // MARK: - Table view data source
     override func numberOfSections(in tableView: UITableView) -> Int {
         return 1
     }

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

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



        let cell = tableView.dequeueReusableCell(withIdentifier: "user", for: indexPath)

        let guys = characters[indexPath.row]

        cell.textLabel?.text = guys.name


   return cell
     }


}




Solution

  • If I understand your question properly, you’d need to implement the didSelectRowAt of the table view method then pass the necessary data to the new view controller:

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
        let character = characters[indexPath.row]
        let charactersViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "characterVC") as! CharacterDetailViewController
        charactersViewController.character = character
        present(charactersViewController.character, animated: true)
    }
    

    For this to work, you will need to have another view controller to show the character once tapped on. Give that view controller the Storyboard ID of "characterVC" in the Identity inspector. The view controller will also need a variable to receive the character object, perhaps:

    class CharacterDetailViewController: UIViewController {
    
      var character: Character?
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
          if let character = character {
            // show the character on the view
          }
      }
    }