Swift 中的 Alamofire 和 ObjectMapper 到 TableView

Alamofire and ObjectMapper to TableView in Swift

我是 swift 的新手,正在尝试从 api 中获取 json 并将其显示给 UITableView,但它不会显示。

这是json:

{
    "success": true,
    "user_id": "somestringhere",
    "devices": [
        {
            "id": "somestringhere",
            "source": "somestringhere",
            "source_text": "somestringhere",
            "logo_url": "somestringhere",
            "is_connected": "0"
        },
        {

用于映射 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?
    
}

我的控制器:

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)
  }
 }    
}
}

我尝试在 Mapper 之后打印设备变量

self.devices = Mapper<PatientDevices>().mapArray(JSONString: json.rawString()!)
print(self.devices)

给我看

Optional([ProjectName.Devices])

我尝试打印 json 响应数据并成功请求,但我无法将其添加到表视图中。 我应该怎么做才能解决这个问题? 我不知道我做错了什么。

首先——一如既往——因为 Swift 4 个库,如 ObjectMapperSwiftyJSON 已经过时,取而代之的是 built-in,高效 Codable协议。避免推荐那些过时库的教程。

关于您的错误,您忽略了根对象,具有键 successuser_iddevices.

的对象

这是一个使用Decodable

的解决方案
  • 删除 SwiftyJSONObjectMapper

  • 将结构替换为

      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
      }
    
  • 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)
                  }
          }
      }
    

    Alamofire 响应 returns 原始数据和 keyDecodingStrategysnake_cased 键转换为 camelCased 结构成员和 logoUrl 被解码为 URL

  • 最后将数据源数组重命名为

      var devices = [Device]()
    

    并删除devices

    之后的所有问号

你错过了主要对象。添加此 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]?

}

同时创建一个新变量来映射主对象

var response: Response?

并改变

self.devices = Mapper<Devices>().mapArray(JSONString: json.rawString()!)

self.response = Mapper<Response>().map(JSONString: json.rawString()!)
self.devices = self.response.devices