【问题标题】:How do I convert raw data of type 'Any' into a concrete type?如何将“任何”类型的原始数据转换为具体类型?
【发布时间】:2020-11-05 20:28:43
【问题描述】:

场景:我创建了一个数据源引擎,它返回数据 各种格式(取决于上下文)使用 Any 作为返回 输入。

这是 remoteDataPublisher 的订阅者:

   remoteDataPublisher
        .eraseToAnyPublisher()
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished:
                print("Publisher Finished")
            case let .failure(anError):
                Swift.print("\nReceived error: ", anError)
            }
        }, receiveValue: { [self] someValue in
            DataSource.shared.rawData = someValue
        }).store(in: &cancellables)

这是接收数据源:

final class DataSource {
    ...

    static let shared = DataSource()
    ...
    var rawData: Any?
    ...
}

由于数据来自多个来源,具体取决于上下文,类型为 Any
在这种情况下,数据类型为:

struct AppleSubRegions: Codable {
    let country, subregion: String
    let data: [AppleDatum]
}

(lldb) po DataSource.shared.rawData!
▿ AppleSubRegions
  - country : "Canada"
  ▿ subregions : 20 elements
    - 0 : "Alberta"
    - 1 : "Calgary"
    - 2 : "Edmonton"
    - 3 : "British Columbia"
    - 4 : "Vancouver"
    - 5 : "Manitoba"
    - 6 : "New Brunswick"
    - 7 : "Newfoundland and Labrador"
    - 8 : "Northwest Territories"
    - 9 : "Halifax"
    - 10 : "Nova Scotia"
    - 11 : "Ontario"
    - 12 : "Ottawa"
    - 13 : "Toronto"
    - 14 : "Prince Edward Island"
    - 15 : "Montreal"
    - 16 : "Quebec"
    - 17 : "Saskatchewan"
    - 18 : "All"
    - 19 : "Yukon Territory"

目标:我想将此“Any”数据类型转换回可用AppleSubRegions”类型;与其他相应类型同上(例如,'[String]' 等);视情况而定,

这是控制台上的原始输出:

{"country":"Canada","subregions":["Alberta","Calgary","Edmonton","British Columbia","Vancouver","Manitoba","New Brunswick","Newfoundland and Labrador","Northwest Territories","Halifax","Nova Scotia","Ontario","Ottawa","Toronto","Prince Edward Island","Montreal","Quebec","Saskatchewan","All","Yukon Territory"]}

(lldb) po type(of: DataSource.shared.rawData)
Swift.Optional<Any>

我试图将“Any”重新投入到 Struct 中,但失败了:

(lldb) po DataSource.shared.rawData as AppleSubRegions
Fatal error: Unexpectedly found nil while unwrapping an Optional value: file __lldb_expr_50/<EXPR>, line 6
2020-11-05 12:21:44.108408-0800 Covid19[68513:2486483] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file __lldb_expr_50/<EXPR>, line 6

问题:如何将 iOS 对象恢复为原生类型?

【问题讨论】:

  • 您是否考虑过使用泛型而不需要使用 Any?
  • 同意乔金。 “使用 Any 作为返回类型” => 不要那样做。严重地。协议,泛型,枚举,任何东西。不要使用任何。 (在这种情况下,泛型可能是正确的答案)

标签: ios swift combine


【解决方案1】:

根据反馈 - 使用 Generics 与数据类型“Any”:

protocol GenericProtocol {
    associatedtype T : Decodable
    var rawData: T {get set}
}

class SomeClass<T: Decodable> {
    var isHistorical: Bool = false
    var continent: String?
    var countryName: String?
    var subRegion: String?
    var rawData: T?
}

// =======================================================

struct AppleSubRegions: Codable {
    let country, subregion: String
    let data: [AppleDatum]
}

struct AppleDatum: Codable {
    let subRegion, subregionAndCity, geoType, date: String
    let driving, transit, walking: Int

    enum CodingKeys: String, CodingKey {
        case subRegion = "sub-region"
        case subregionAndCity = "subregion_and_city"
        case geoType = "geo_type"
        case date, driving, transit, walking
    }
}

// ---------------------------------------------------------------------------

// 1) String ----
let stringClass = SomeClass<String>()
stringClass.rawData = "Ric"
print("String Type: ", stringClass.rawData! as String)

// 2) Int ----
let intClass = SomeClass<Int>()
intClass.rawData = 123
print("Int Type: ", intClass.rawData! as Int)

// 3) Apple SubRegions ---
let appleDatum = AppleDatum(subRegion: "Ontario", subregionAndCity: "Ontario", geoType: "sub-region", date: "2020-11-05", driving: 1, transit: 2, walking: 3)
let appleSubRegion = AppleSubRegions(country: "Canada", subregion: "Ontario", data: [appleDatum])

let appleClass = SomeClass<AppleSubRegions>()
appleClass.rawData = appleSubRegion

print("Apple SubRegion Type: ", appleClass.rawData!)

let appleData = appleClass.rawData

let country = appleData?.country
print("Country: \(country!)")

print("The End")

输出:

String Type:  Ric
Int Type:  123
Apple SubRegion Type:  AppleSubRegions(country: "Canada", subregion: "Ontario", data: [__lldb_expr_25.AppleDatum(subRegion: "Ontario", subregionAndCity: "Ontario", geoType: "sub-region", date: "2020-11-05", driving: 1, transit: 2, walking: 3)])
Country: Canada
The End

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    相关资源
    最近更新 更多