Tableview with JSON Data in Swift 4.2 - ios

I'm new to Swift and I am at my wit's end, so please be kind to me.
I am building an app which downloads data from an url by posting a specific ID and getting back an JSON array. The JSON looks like this:
[{"group":"500","from":"2019-01-01","to":"2019-01-05"},{...}]
It has the group number as "group" and a start Date "from" and an end date "to".
I want to let the different groups shown in a Tableview with the From and To-Dates as well. I managed to download the data correctly but I failed by showing them in a tableview.
My code is down below. Maybe someone of you can find out what I've done wrong.
When I run the project I get an empty table.
import UIKit
typealias Fahrten = [FahrtenElement]
struct FahrtenElement: Codable {
let group: String?
let from: String?
let to: String?
enum CodingKeys: String, CodingKey {
case group = "group"
case from = "from"
case to = "to"
}
}
class BookingsController: UITableViewController {
var tableview: UITableView!
var groups = [Fahrten]()
// MARK: - Table view data source
override func viewDidLoad() {
super.viewDidLoad()
downloadData()
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let label = UILabel()
label.text = "Groups"
label.backgroundColor = .yellow
return label
}
// Section
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.groups.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//lblname to set the title from response
cell.textLabel?.text = "Group \(String(describing: groups[indexPath.row].group))"
cell.detailTextLabel?.text = "From \(String(describing: groups[indexPath.row].from)) to \(String(describing: groups[indexPath.row].to))"
return cell
}
func downloadData() {
let id = "..."
let url = URL(string: "...")!
// request url
var request = URLRequest(url: url)
// method to pass data POST - cause it is secured
request.httpMethod = "POST"
// body gonna be appended to url
let body = "id=(\(id))"
// append body to our request that gonna be sent
request.httpBody = body.data(using: .utf8)
URLSession.shared.dataTask(with: request) { (data, response, err) in
guard let data = data else { return }
do {
let groups = try JSONDecoder().decode(Fahrten.self, from: data)
print(groups)
self.tableview.reloadData() // I get an crash here: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value }
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}

From what I can see it looks like you are emptying the array and not reloading the data.
You should assign the resulting groups property to self.groups and then reload the data.
DispatchQueue.main.async {
self.groups = groups // change here
self.tableview.reloadData()
}

Try this code.
Your model.
typealias Fahrten = [FahrtenElement]
struct FahrtenElement: Codable {
let group: String
let from: String
let to: String
enum CodingKeys: String, CodingKey {
case group = "group"
case from = "from"
case to = "to"
}
}
Use it, I am using it with local json with same structure.
func getFehData(){
let url = Bundle.main.url(forResource: "fah", withExtension: "json")!
do {
let jsonData = try Data(contentsOf: url)
let fahrten = try? JSONDecoder().decode(Fahrten.self, from: jsonData)
print(fahrten)
}
catch {
print(error)
}
}
Output : (Dummy data)

Related

Swift - display specific data for each tableview section

I'm working with CocktailDB.
By creating a request I get a JSON file, parse it with Decodable protocol. From JSON I get all drinks' categories and display them as the sections of my tableview.
In each tableview section I want to display drinks from specific category (section's header). One drink per section cell from the category (drink's strDrink (name) and strDrinkThumb (image)).
I have a method that creates a request to get drinks from specific category - getDrinksFrom(category: String).
Please advice how can I call this method for specific section to get and display drinks from specific category in this section?
My code:
class ViewController: UIViewController {
var drinks = [Drink]()
var categories = [Category]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getCategories()
getDrinksFrom(category: "Cocoa")
}
func getCategories() {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
self.categories = try JSONDecoder().decode(Categories.self, from: data!).drinks
DispatchQueue.main.async {
self.tableView.reloadData()
}
print(self.categories)
} catch {
print(error)
}
}
}.resume()
}
func getDrinksFrom(category: String) {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=\(category)")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
self.drinks = try JSONDecoder().decode(Drinks.self, from: data!).drinks
DispatchQueue.main.async {
self.tableView.reloadData()
}
print(self.drinks)
} catch {
print(error)
}
}
}.resume()
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return categories.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return categories[section].strCategory
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "drinkCell") as! DrinkCell
cell.drinkName.text = drinks[indexPath.row].strDrink
let url = drinks[indexPath.row].strDrinkThumb
cell.drinkImage.downloaded(from: url)
return cell
}
}
// to download an image from web
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
Category Model:
struct Categories:Decodable {
var drinks: [Category]
}
struct Category:Decodable {
var strCategory: String
}
Drink Model:
struct Drinks:Decodable {
var drinks: [Drink]
}
struct Drink:Decodable {
var strDrink: String
var strDrinkThumb: String
}
What I have for know:
JSON structure:
My suggestion is to create a custom struct Category with name and drinks for the sections. It does not conform to Decodable, this is intended
struct Category {
let name : String
var drinks : [Drink]
}
and an appropriate data source array
var categories = [Category]()
then load and parse the categories with traditional JSONSerialization and populate the array by mapping the names. Further add a completion handler
func getCategories(completion: #escaping () -> Void) {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let error = error { print(error); return }
do {
let result = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
let categoryNames = result["drinks"] as! [[String:String]]
self.categories = categoryNames.map{ Category(name: $0["strCategory"]!, drinks:[])}
completion()
} catch {
print(error)
}
}.resume()
}
To avoid naming confusion (too many drinks) name the root struct Response
struct Response : Decodable {
let drinks: [Drink]
}
Load the data related to a category and assign the drinks array to the corresponding array in categories
func getDrinksFrom(category: String) {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=\(category)")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let error = error { print(error); return }
do {
let drinks = try JSONDecoder().decode(Response.self, from: data!).drinks
guard let index = categories.firstIndex(where: {$0.name == category}) else { return }
self.categories[index].drinks = drinks
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}.resume()
}
and replace viewDidLoad with
override func viewDidLoad() {
super.viewDidLoad()
getCategories { [weak self] in
self?.getDrinksFrom(category: "Cocoa")
}
}
Finally change the table view data source methods to match the section structure
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return categories.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return categories[section].name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories[section].drinks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "drinkCell") as! DrinkCell
let category = categories[indexPath.section]
let drink = category.drinks[indexPath.row]
cell.drinkName.text = drink.strDrink
let url = drink.strDrinkThumb
cell.drinkImage.downloaded(from: url)
return cell
}
}
You can also put both functions together and load all drinks for all categories
func loadAllCategories() {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let error = error { print(error); return }
do {
let result = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
let categoryNames = (result["drinks"] as! [[String:String]]).map{$0["strCategory"]!}
let group = DispatchGroup()
for category in categoryNames {
let categoryURLString = "https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=\(category)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let categoryURL = URL(string: categoryURLString)!
group.enter()
let categoryTask = URLSession.shared.dataTask(with: categoryURL) { (categoryData, _, categoryError) in
defer { group.leave() }
if let categoryError = categoryError { print(categoryError); return }
do {
let drinks = try JSONDecoder().decode(Response.self, from: categoryData!).drinks
self.categories.append(Category(name: category, drinks: drinks))
} catch {
print(error)
}
}
categoryTask.resume()
}
group.notify(queue: .main) {
self.tableView.reloadData()
}
} catch {
print(error)
}
}.resume()
}
This is just a pseudocode, which will give you an idea how you can proceed further. The code has not been tested.
Create an array of sections to be loaded.
var sections: [Sections] = []
In you tableview delegates you can create a struct for the sections that you need to load, which will help you to identify the section in cell for row index path where you can call API based on categories.
extension ViewController: UITableViewDataSource, UITableViewDelegate {
struct Sections {
static var count = 0
// In stantiate table view headers index order
enum SectionType {
case SoftDrink
case OrdinaryDrink
case MilkShake
}
var type: SectionType?
var section: Int?
var rows: Int?
}
func setUpTableView() {
// Set Up Tableview Data
if check if Drink is type of SoftDrink /*If you sections are loaded dynamic u can add condition*/ {
sections.append(Sections(type: .SoftDrink, section: Sections.count, rows: 1))
Sections.count += 1
}
Sections.count = 0
}
func numberOfSections(in _: UITableView) -> Int {
sections.count
}
func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
sections[section].rows ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var tableCell: UITableViewCell = UITableViewCell()
guard let type = sections[indexPath.section].type else {
tableCell.selectionStyle = .none
return tableCell
}
switch type {
case .SoftDrink: break
// Instantiate cell and API calls.
case .OrdinaryDrink: break
// Instantiate cell and API calls.
case .MilkShake: break
// Instantiate cell and API calls.
}
tableCell.selectionStyle = .none
return tableCell
}
}
setUpTableView() can be called in viewDidLoad Method.

App Crashes After Second API Call (Swift)

I'm trying to fetch data from an API through an HTTP get method in Swift 5. It successfully loads the data on launch, but when I refresh the page it says the "index is out of range", this is because the data is no longer be fetched in my logged, hence there is nothing in the index. Is this a common issue or does this just pertain to me? I've attached my code below and have highlighted where the error shows up. Thank you!
import UIKit
import Foundation
class TheClass: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var pageView: UITableView!
struct StocksObject {
var volume: String?
}
struct Response: Codable {
let _type: String?
let readLink: String?
let totalEstimatedMatches: Int?
let value: [Value]?
}
struct QueryContext: Codable {
let originalQuery: String?
let adultIntent: Bool?
}
struct Value: Codable {
let name: String?
}
var stocks_object = [StocksObject]()
var news_object = [Value]()
override func viewDidAppear(_ animated: Bool) {
self.news_object.removeAll()
self.getNews()
}
override func viewDidLoad() {
super.viewDidLoad()
getData()
getNews()
pageView.delegate = self
pageView.dataSource = self
}
func getNews() {
let request = NSMutableURLRequest(url: NSURL(string: "https://example.com")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data else { return }
do {
let obj: Response = try JSONDecoder().decode(Response.self, from: data)
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
let objectReview = Value(name: obj.value?[0].name)
self.news_object.append(objectReview)
print("\(String(describing: obj.value?[0].name))")
print("\(String(describing: obj.value?[2].name))")
} catch {
print("ERROR: \(error)")
self.performSegue(withIdentifier: "InvalidSymbol", sender: nil)
}
}.resume()
}
func getData() {
let url = URL(string: "https://example2.com")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {
(response, data, error) in
if let data = data {
do {
let json = try JSONDecoder().decode(Root.self,from: data)
let Volume = json.data.first?.volume
struct Root: Codable {
let data: [Datum]
}
struct Datum: Codable {
let volume: String
}
print(json)
let object = StocksObject(volume: Volume)
self.stocks_object.append(object)
DispatchQueue.main.async {
self.pageView.reloadData()
}
} catch {
print(error)
}
}
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 825
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stocks_object.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! StockCell
let object = stocks_object[indexPath.row]
//Error is coming in here:
let objectNews = news_object[indexPath.row]
cell.volume.text = object.volume
cell.newsOne.text = objectNews.name
return cell
}
}
Inside viewDidAppear, you need to empty your "news_object" Array when page loads and then call self.getNews() inside viewDidAppear.
Inside viewDidAppear:
self.news_object.removeAll()
self.getNews()
Since you edited your question so here is the reason why you are facing this error.
For above code you need to create switch statement that check which array.count to return and do same in cellForRowAt. Because they both have different length that's the reason you are facing error "Out of Range"
I hope its clear now.

Unable to display parsed JSON data into UITableView

I am parsing JSON data into a model object nested structure. I am also sorting the model and appending to my sortedArr array which is sorted alphabetically. I am attempting to display the names and other information such as biography into my table view. When trying to display the names of the indexPath into my table view cell I am unable to reach the members of the array, such as fullName, biography, etc.
struct Response: Decodable {
struct Students: Decodable {
var fullName :String
var biography:String
var emailAddress:String
enum CodingKeys: String, CodingKey {
case fullName = "full_name"
case biography
case emailAddress = "email_address"
}
}
var students:[Students]
}
var sortedArr = [[Response.Students]]()
func parseData(){
guard let url = URL(string: "xxxxxx") else {return}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Error")
return
}
do {
let response = try! JSONDecoder().decode(Response.self, from: dataResponse)
self.sortedArr = response.students.sorted{$0.fullName < $1.fullName}
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sortedArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! EmployeeTableViewCell
let emps = sortedArr[indexPath.row]
cell.titleLabel.text = emps.fullName //has no member fullName
return cell
}

Why am I getting a blank UITableView after parse JSON in Swift 4?

I can't figure out why the cells don't return with data.
I can parse normally using the Decodable, which means that is working.
I've been trying all the methods I find without success.
struct MuscleGroup: Decodable {
let ExcerciseID: String
let description: String
let excerciseName: String
let muscleGroup: String
}
class ExerciseListViewController: UITableViewController {
var muscleGroup = [MuscleGroup]()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return muscleGroup.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExerciseList", for: indexPath) as! ExcerciseList
let muscle = muscleGroup[indexPath.row]
cell.textLabel!.text = muscle.excerciseName
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(self.muscleGroup[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
getJson()
}
func getJson(){
guard let url = URL(string: "https://jsonurl") else { return }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let muscles = try JSONDecoder().decode([MuscleGroup].self, from: data)
for muscle in muscles {
let muscleGroup = muscle.excerciseName
print(muscleGroup)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
} catch {
print(error)
}
}
}.resume()
}
If I change the var muscleGroup = String to ["Chest", "Back", "Abdominals","Arms", "Legs"] it returns correctly.
Also, the print result on the console returns all the data that needs to be on the Table View.
What am I doing wrong?
As you probably want to use the entire struct
Replace
var muscleGroup = [String]()
with
var muscleGroups = [MuscleGroup]()
Replace
let muscles = try JSONDecoder().decode([MuscleGroup].self, from: data)
for muscle in muscles {
let muscleGroup = muscle.excerciseName
print(muscleGroup)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
with
self.muscleGroups = try JSONDecoder().decode([MuscleGroup].self, from: data)
DispatchQueue.main.async {
self.tableView.reloadData()
}
Replace
cell.textLabel?.text = self.muscleGroup[indexPath.row]
with
cell.textLabel?.text = self.muscleGroups[indexPath.row].muscleGroup
In your getJson function this line
let muscleGroup = muscle.excerciseName
is creating a new local variable called muscleGroup, change the line to be
self.muscleGroup.append(muscle.excerciseName)
i.e. get rid of the let and append the value to the main array variable
Also move the
DispatchQueue.main.async {
self.tableView.reloadData()
}
to be outside of the for loop of muscles as you are forcing the table to reload for each entry rather than when you are finished

pass json id from one table view controller into another table view controller in swift 3

I already new in swift 3 and objetive c, right now I am stuck into how can I pass the id of each row to another table view controller when the user tap in the row the user want to go.
Here is the json data firstFile:
[
{"id_categoria":"1","totalRows":"323","nombre_categoria":"Cirug\u00eda"},
{"id_categoria":"2","totalRows":"312","nombre_categoria":"Med Interna"},
{"id_categoria":"3","totalRows":"6","nombre_categoria":"Anatomia"},
{"id_categoria":"4","totalRows":"24","nombre_categoria":"Anestesiologia"},
...]
Here is my first table view controller:
import UIKit
class CatMedVC: UIViewController, UITableViewDataSource {
#IBAction func volver(_ sender: Any) { }
#IBOutlet weak var listaCategoria: UITableView!
var fetchedCategoria = [Categoria]()
override func viewDidLoad() {
super.viewDidLoad()
listaCategoria.dataSource = self
parseData()
}
override var prefersStatusBarHidden: Bool{
return true
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedCategoria.count
}
public func tableView(_ tableView: UITableView, cellForRowAt IndexPath: IndexPath) ->
UITableViewCell {
let cell = listaCategoria.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel?.text = fetchedCategoria[IndexPath.row].esp
cell?.detailTextLabel?.text = fetchedCategoria [IndexPath.row].totalRows
return cell!
}
func parseData() {
let url = "http://www.url.com/firstFile.php" //in json format
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request) { (data, response, error) in
if(error != nil) {
print("Error")
}
else {
do {
let fetchedData = try JSONSerialization.jsonObject(with:data!, options: .mutableLeaves) as! NSArray
//print(fetchedData)
for eachFetchedCategoria in fetchedData {
let eachCategoria = eachFetchedCategoria as! [String : Any]
let nombre_categoria = eachCategoria["nombre_categoria"] as! String
let totalRows = eachCategoria["totalRows"] as! String
let id_categoria = eachCategoria["id_categoria"] as! String
self.fetchedCategoria.append(Categoria(nombre_categoria: nombre_categoria, totalRows: totalRows, id_categoria: id_categoria))
}
//print(self.fetchedCategoria)
self.listaCategoria.reloadData()
}
catch {
print("Error 2")
}
}
}
task.resume()
}
}
class Categoria {
var nombre_categoria : String
var totalRows : String
var id_categoria : String
init(nombre_categoria : String, totalRows : String, id_categoria : String) {
self.nombre_categoria = nombre_categoria
self.totalRows = totalRows
self.id_categoria = id_categoria
}
}
So I need pass the id_categoria String into the another table view to show the data for the id selected previously...here I don't know how to do it...I have the json file waiting for the id selected previously..but I don't know how to catch it into the url
Here the second table view:
import UIKit
class EspMedVC: UITableViewController {
var TableData:Array< String > = Array < String >()
var EspecialidadArray = [String]()
#IBAction func volver(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
get_data_from_url("http://www.url.com/secondFile.php?id=") // Here I need to put the id_categoria String in json format
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
return cell
}
func get_data_from_url(_ link:String)
{
let url:URL = URL(string: link)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
self.extract_json(data!)
})
task.resume()
}
func extract_json(_ data: Data)
{
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
}
catch
{
return
}
guard let data_list = json as? NSArray else
{
return
}
if let nombre_especialidad = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let nombre_esp_obj = nombre_especialidad[i] as? NSDictionary
{
if let nombre_especialidad = nombre_esp_obj["subesp"] as? String
{
if let totalRows = nombre_esp_obj["totalRows"] as? String
{
TableData.append(nombre_especialidad + " [" + totalRows + "]")
}
}
}
}
}
DispatchQueue.main.async(execute: {self.do_table_refresh()})
}
func do_table_refresh()
{
self.tableView.reloadData()
}
}
This is a rough guide, please search for the methods in the documentation or here at other questions inside stackoverflow.
1) Add a variable inside your EspMedVC that will hold the "id_categoria String" that should be displayed.
2) Add a variable inside your CatMedVC that will hold the "id_categoria String" that the user selected.
3) Implement the "didSelectRow" delegate method from your tableview inside the "CatMedVC", inside this method you should set the variable set on step 2.
4) Implement the "prepareForSegue" method inside your CatMedVC, inside the the implementation you should retrieve the destination VC, cast it to "EspMedVC" and set the variable from step 1.
5) On the "viewDidLoad" from EspMedVC you can now use the variable set on step 2 to query your JSON and update the table view accordingly.

Resources