[英]Alamofire and ObjectMapper to TableView in Swift
I am new to swift and trying to fetch json from an api and show it to UITableView but it won't show.我是 swift 的新手,并试图从 api 获取 json 并将其显示给 Z1AEC67449629C543B18ZAE0 但不会显示。
This is the json:这是 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:映射 json 数据:
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:我的 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我尝试在 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.我尝试打印 json 响应数据并请求成功,但是我无法将其添加到 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.首先 - 一如既往 - 自从 Swift 4 库,如ObjectMapper
和SwiftyJSON
已经过时,有利于内置的、高效的Codable
协议。 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
.关于您的错误,您忽略了根 object,object 键为success
, user_id
和devices
。
This is a solution using Decodable
这是使用Decodable
的解决方案
Drop SwiftyJSON
and ObjectMapper
放弃SwiftyJSON
和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将loadData
替换为
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
Alamofire 响应返回原始数据, keyDecodingStrategy
将snake_cased键转换为camelCased结构成员,并且logoUrl
被解码为URL
Finally rename the data source array to最后将数据源数组重命名为
var devices = [Device]()
and remove all question marks after devices
并删除devices
后的所有问号
You are missing the main object.您缺少主要的 object。 Add this class in addition to your Device class.除了您的设备 class 之外,添加此 class。
import Foundation
import ObjectMapper
class Response: Mappable {
required init?(map: Map) {
}
func mapping(map: Map) {
success<-map["success"]
user_id<-map["user_id"]
devices<-map["devices"]
}
var success : Bool?
var user_id : String?
var devices: [Device]?
}
Also create a new variable to map the main object同时创建一个新变量到 map 主 object
var response: Response?
and change和改变
self.devices = Mapper<Devices>().mapArray(JSONString: json.rawString()!)
to至
self.response = Mapper<Response>().map(JSONString: json.rawString()!)
self.devices = self.response.devices
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.