I am new to swift and trying to fetch json from an api and show it to UITableView but it won't show.
This is the json:
{
"success": true,
"user_id": "somestringhere",
"devices": [
{
"id": "somestringhere",
"source": "somestringhere",
"source_text": "somestringhere",
"logo_url": "somestringhere",
"is_connected": "0"
},
{
For mapping the json data:
import Foundation
import ObjectMapper
class Devices: Mappable {
required init?(map: Map) {
}
func mapping(map: Map) {
id<-map["id"]
source<-map["source"]
sourceText<-map["source_text"]
logo<-map["logo_url"]
isConnected<-map["is_connected"]
}
var id : String?
var source : String?
var sourceText : String?
var logo : String?
var isConnected : Bool?
}
My Controller:
import Foundation
import UIKit
import SwiftyJSON
import Alamofire
import ObjectMapper
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var devices : [Devices]?
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(HomeTableViewCell.nib(), forCellReuseIdentifier: HomeTableViewCell.identifier)
tableView.delegate = self
tableView.dataSource = self
loadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return devices?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: HomeTableViewCell.identifier, for: indexPath) as! HomeTableViewCell
cell.setup(title: "\(devices?[indexPath.row].sourceText)", iconLink: "\(devices?[indexPath.row].logo)")
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
func loadData(){
let base = Config().base
let endPoint = Config.EndPoint()
let patientId = User().id
let url = base + endPoint.showDevices
let header: HTTPHeaders = [
"Content-Type": "application/json",
]
let params: Parameters = [
"patient_id" : patientId
]
let code = Code(id: id)
AF.request(url, method: .get, parameters: params, encoding: URLEncoding.default, headers:header).validate()
.response{ (response) in
switch response.result {
case .success(let value):
let json = JSON(value)
self.devices = Mapper<Devices>().mapArray(JSONString: json.rawString()!)
self.tableView.reloadData()
case .failure(let error):
print(error)
}
}
}
}
I tried printing the device variable after the Mapper
self.devices = Mapper<PatientDevices>().mapArray(JSONString: json.rawString()!)
print(self.devices)
and shows me
Optional([ProjectName.Devices])
I tried to print json response data and request successful however I couldn't add it to tableview. What should I do to solve this problem? I don't know what I am doing wrong.
First of all – as always – since Swift 4 libraries like ObjectMapper
and SwiftyJSON
have become obsolete in favor of built-in, efficient Codable
protocol. Avoid tutorials which suggest those outdated libraries.
Regarding your mistake you are ignoring the root object, the object with keys success
, user_id
and devices
.
This is a solution using Decodable
Drop SwiftyJSON
and ObjectMapper
Replace the structs with
struct Root : Decodable {
let success : Bool
let userId : String
let devices : [Device]
}
struct Device : Decodable {
let id : String
let source : String
let sourceText : String
let logoUrl : URL
let isConnected : String // this value is String, not Bool
}
Replace loadData
with
func loadData(){
let base = Config().base
let endPoint = Config.EndPoint()
let patientId = User().id
let url = base + endPoint.showDevices
let header: HTTPHeaders = [
"Content-Type": "application/json",
]
let params: Parameters = [
"patient_id" : patientId
]
let code = Code(id: id)
AF.request(url, parameters: params, headers:header).validate()
.responseData { (response) in
switch response.result {
case .success(let data):
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Root.self, from: data)
self.devices = result.devices
self.tableView.reloadData()
} catch { print(error) }
case .failure(let error):
print(error)
}
}
}
The Alamofire response returns raw data and the keyDecodingStrategy
converts the snake_cased keys to camelCased struct members and logoUrl
is decoded as URL
Finally rename the data source array to
var devices = [Device]()
and remove all question marks after devices