Swift 可解码列表或混合类型的项目

问题描述

在我最近开发的几个应用程序中,我需要阅读混合类型的项目列表。 “现实生活”情况的一个很好的例子是文章中的项目列表:有标题、副标题、正文、图像等。

我想出了这样的东西:

// Sample data:
//
// {
//    items: [
//         {
//             "type": "a",//             "a": "This one is A"
//         },//         {
//             "type": "b",//             "b": "This one is B"
//         }
//     ]
// }

import Foundation

// MARK: - "Root" protocol for all decodable items

protocol Item: Decodable {}

// MARK: - Items

struct ItemA: Item { let a: String }
struct ItemB: Item { let b: String }

// MARK: - Extractor

/// Helper for extracting items
struct ItemExtractor: Decodable {
    
    enum TypeKey: String,Decodable {
        case a
        case b
    }
    
    let item: Item
    
    // MARK: - Decodable compliance
    
    enum CodingKeys: String,CodingKey {
        case type
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        let type = try values.decode(TypeKey.self,forKey: .type)
        
        let itemValues = try decoder.singleValueContainer()
        
        // In particular,looking to eliminate this `switch`
        switch type {
        case .a:
            item = try itemValues.decode(ItemA.self)
        case .b:
            item = try itemValues.decode(ItemB.self)
        }
    }
}

// MARK: - Container

/// Container of items
struct MyList: Decodable {
    let items: [Item]
    
    // MARK: - Decodable compliance
    
    enum CodingKeys: String,CodingKey {
        case items
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        
        let extractors = try values.decode([ItemExtractor].self,forKey: .items)
        items = extractors.map { $0.item }
    }
}
  • 数据文件中项目的类型用“类型”字段标记
  • ItemExtractor 助手读取类型​​并根据其类型初始化项目;
  • 然后从 ItemExtractor 数组中取出这些项目并将其添加到 MyList 结构中的项目列表中。

现在的问题是:有没有办法概括这段代码来避免 ItemExtractor 中的 switch 语句,如果有很多不同类型的项目,这将特别有用,或者,也许,有完全不同的方法吗?

期待更好的解决方案, ——巴格兰

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)