具有不同种类的JSON数据的通用UITableViewCell

问题描述 投票:0回答:2

我喜欢使用single tableViewCell实例(而不是创建单独的单元格)来处理不同类型的数据;通过为此创建协议使用了一种简单的通用方法,但是如何以清晰的方式从JSON填充数据(通过避免切换大小写)?

protocol CellData {
    var title: String { get set }
    var subTitle: String { get set }
    var image: String { get set }
}

对于singleCell

@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subTitleLabel: UILabel!
@IBOutlet weak var imageView: UIImageView!
{
  "data": [
    {
      "type": "company",
      "data": {
        "name": "Google",
        "sector": "IT",
        "logo": "https://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif"
      }
    },
    {
      "type": "person",
      "data": {
        "name": "Bill Gates",
        "occupation": "Microsoft CEO",
        "picture": "https://img.etimg.com/thumb/msid-66398917,width-640,resizemode-4,imgsize-702055/words-of-wisdom.jpg"
      }
    },
    {
      "type": "song",
      "data": {
        "name": "Beat It",
        "singer": "M.Jackson",
        "thumbnail": "https://cdn.smehost.net/michaeljacksoncom-uslegacyprod/wp-content/uploads/2019/08/Sept2019Mobile.jpg"
      }
    },
    {
      "type": "vehicle",
      "data": {
        "name": "Silver Silver",
        "brand": "Silver",
        "photo": "https://images.pexels.com/photos/112460/pexels-photo-112460.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
      }
    }
  ],
  "error": null
}
ios swift
2个回答
0
投票

您可以使用带有可选属性的模型,这意味着它们不一定总是需要设置所有属性,但是正如Vadian所提到的,在某些时候您将需要映射所接收的内容。

您还可以将所有非图像或标题的键定义为字幕(例如,部门或职业或歌手或品牌)。


0
投票

如果您对可以预期的密钥有保证,那么您可以尝试解析找到的第一个密钥的数据:

struct CellDataEnvelope: Decodable {
  let data: CellData
  let type: CellDataType

  enum CellDataType: String, Decodable {
    case company
    case person
    case song
    case vehicle
  }
}

struct CellData: Decodable {
  let title: String
  let subTitle: String
  let image: String

  enum CodingKeys: CodingKey {
    // title
    case name

    // subTitle
    case sector
    case occupation
    case singer
    case brand

    // image
    case thumbnail
    case picture
    case logo
    case photo
  }
}

extension CellData {
  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    self.title = try container.decode(String.self, forKey: .name)

    self.subTitle = try tryDecodeString(in: container, keys: [.sector, .occupation, .singer, .brand])
    self.image = try tryDecodeString(in: container, keys: [.thumbnail, .picture, .logo, .photo])
  }
}

// Attempts to decode a String value from an array of keys, returns the first one to successfully decode.
private func tryDecodeString(
  in container: KeyedDecodingContainer<CellData.CodingKeys>,
  keys: [CellData.CodingKeys]
) throws -> String {
  for key in keys {
    if let value = try? container.decode(String.self, forKey: key) {
      return value
    }
  }

  throw DecodingError.dataCorrupted(
    .init(
      codingPath: [],
      debugDescription: "Invalid data"
    )
  )
}


let models = try JSONDecoder().decode([CellDataEnvelope].self, from: Data(json.utf8))

如果密钥列表将大大增加或者您对它们没有保证,这可能会变得很笨拙。

© www.soinside.com 2019 - 2024. All rights reserved.