代码之家  ›  专栏  ›  技术社区  ›  Bruno Vavretchek

JSON模型建议

  •  0
  • Bruno Vavretchek  · 技术社区  · 6 年前

    我必须创建一个好的模型,将从JSON接收到的数据传递给我的其他控制器。你们怎么做到的?我需要在项目中的任何地方访问结构中的这些属性,以便能够填充UI组件等。

    这是我的API响应文件:

    import Foundation
    import Alamofire
    
    struct Description: Decodable {
        let data: [data]
    }
    
    struct data: Decodable {
    
        let id:Int?
        let descricao:String?
        let urlImagem:String?
    }
    
    func callApi(completion: @escaping (String, String) -> Void) {
    
        guard let _url = URL(string: "https://alodjinha.herokuapp.com/categoria")else{return}
        Alamofire.request(_url).responseJSON { (response) in
    
            guard let info = response.data else{return}
    
            do{
                let dataParsed = try JSONDecoder().decode(Description.self, from: info)
    
                for aData in dataParsed.data {
    
    
                    completion(aData.descricao!, aData.urlImagem!)
                }
    
            }catch{
            print("Error serialization: \(error)")
    
    
    }
    }
    }
    

    这是我收到的JSON模型:

    {
      "data": [
        {
          "id": 1,
          "descricao": "Games",
          "urlImagem": "http:\/\/39ahd9aq5l9101brf3b8dq58.wpengine.netdna-cdn.com\/wp-content\/uploads\/2013\/06\/3D-Gaming.png"
        },
        {
          "id": 2,
          "descricao": "Livros",
          "urlImagem": "http:\/\/4.bp.blogspot.com\/-6Bta1H9d22g\/UJAIJbqcHhI\/AAAAAAAAKi4\/hvgjWrlFc64\/s1600\/resenha-missiologia.png"
        },
        {
          "id": 3,
          "descricao": "Celulares",
          "urlImagem": "http:\/\/pt.seaicons.com\/wp-content\/uploads\/2015\/11\/Mobile-Smartphone-icon.png"
        },
        {
          "id": 4,
          "descricao": "Inform\u00e1tica",
          "urlImagem": "http:\/\/portal.ifrn.edu.br\/campus\/ceara-mirim\/noticias\/ifrn-oferece-curso-de-informatica-basica-para-pais-dos-estudantes\/image_preview"
        },
        {
          "id": 5,
          "descricao": "Eletrodom\u00e9stico",
          "urlImagem": "http:\/\/classificados.folharegiao.com.br\/files\/classificados_categoria\/photo\/8\/sm_4d5ed3beb0f31b61cb9a01e46ecd0cf9.png"
        },
        {
          "id": 6,
          "descricao": "TVs",
          "urlImagem": "http:\/\/i.utdstc.com\/icons\/256\/terrarium-tv-android.png"
        },
        {
          "id": 7,
          "descricao": "Filmes e S\u00e9ries",
          "urlImagem": "https:\/\/pbs.twimg.com\/profile_images\/801033586438733824\/91Y_N91t_reasonably_small.jpg"
        },
        {
          "id": 8,
          "descricao": "M\u00f3veis e Decora\u00e7\u00f5es",
          "urlImagem": "https:\/\/image.flaticon.com\/icons\/png\/128\/148\/148188.png"
        },
        {
          "id": 9,
          "descricao": "Moda, Beleza e Perfumaria",
          "urlImagem": "http:\/\/icon-icons.com\/icons2\/196\/PNG\/128\/fashion_23852.png"
        },
        {
          "id": 10,
          "descricao": "Papelaria",
          "urlImagem": "http:\/\/esen.pt\/in\/images\/stories\/skills_256.png"
        }
      ]
    }
    

    非常感谢!

    1 回复  |  直到 6 年前
        1
  •  1
  •   staticVoidMan    6 年前

    1.模型重构

    首先,让我们介绍一下产品的型号名称 data .
    成功 ImageData 因为类型名应该是Pascal大小写的(这只是一个很好的编码约定)。例如 ClassName , StructName , PascalCase .
    我们也不希望它被称为 Data 因为那样会超负荷 Foundation 是的 数据 类型

    因此,我们的模型将是:

    struct Description: Decodable {
        let data: [ImageData]
    }
    
    struct ImageData: Decodable {
        let id: Int
        let descricao: String
        let urlImagem: String
    }
    

    2.单身

    我需要在任何我想访问的地方访问我的结构中的这些属性 在项目中

    在这种情况下,我将使用一个引用图像数组的单例。

    例子:

    class SharedManager {        
        static let shared = SharedManager()
        private init() {}
    
        var images: [ImageData]?
    }
    

    3.服务助理

    让我们编写一个名为 APIHelper 就像一个服务助手。在这里,我们将有 Alamofire 因此,让我们在这方面也有所改进。

    1. 让我们重新命名 callApi(completion:) 去做更有意义的事,比如, getImages(completion:)
    2. 为了方便起见,让我们将其设置为类方法。
    3. 也不是完成闭包 (String, String) ,让它提供 [ImageData]? ; i、 e.一系列 图像数据 模型。
      • 以便以后在应用程序中轻松访问
      • 如果url无效或请求/解析失败(保持简单),此数组是可选的

    :

    class APIHelper {
    
        class func getImages(completion: @escaping ([ImageData]?)->Void) {
            guard let url = URL(string: "https://alodjinha.herokuapp.com/categoria")
                else {
                    completion(nil)
                    return
            }
    
            Alamofire
                .request(url)
                .responseJSON { (response) in
                    switch response.result {
                    case .success(_):
                        do {
                            let myImages = try JSONDecoder().decode(Description.self,
                                                                    from: response.data!)
                            completion(myImages.data)
                        }
                        catch {
                            print(error)
                            completion(nil)
                        }
                    case .failure(let error):
                        print(error)
                        completion(nil)
                    }
            }
        }
    
    }
    

    4.在singleton中设置数组

    呼叫 getImages(完成:) 一次设定 SharedManager.shared.images 就像这样:

    APIHelper.getImages { (imageData) in
        print(imageData)
        SharedManager.shared.images = imageData
    }
    

    5.用法

    现在,您应该可以通过 共享管理器。共享。图像 随时随地(当然在你们的应用范围内)

    这只是基本的阵列处理逻辑,但以下是几个示例:

    • 循环浏览它们:

      for imageData in SharedManager.shared.images ?? [] {
          print(imageData)
      }
      
    • 在特定索引处访问图像

      let imageIndex = 1
      let imageURL = SharedManager.shared.images?[imageIndex].urlImagem
      print(imageURL)
      
    • 查找具有特定id的图像:

      let imageIDToFind = 7
      let foundImage = SharedManager.shared.images?.first { $0.id == imageIDToFind }
      print(foundImage)