简体   繁体   English

Swift 中的 Alamofire 和 ObjectMapper 到 TableView

[英]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 库,如ObjectMapperSwiftyJSON已经过时,有利于内置的、高效的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 键为successuser_iddevices

This is a solution using Decodable这是使用Decodable的解决方案

  • Drop SwiftyJSON and ObjectMapper放弃SwiftyJSONObjectMapper

  • 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 withloadData替换为

     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 响应返回原始数据, keyDecodingStrategysnake_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM