如何解决使用要通过JSONDecoder解析的模型的通用值相对于静态model.self
场景:我想使用通用功能来访问各个端点。因此,我试图创建样板代码来处理各种数据模型(struct.self)及其关联的URL。
以下是几个共享 URL URLSession +解码代码的模型:
// MARK: - Region
struct Region: Codable {
let country: String
let subregions: [String]
}
// MARK: - SubRegion
struct SubRegion: Codable {
let country: String
let subregion: Sub
let data: [Datum]
}
这里是一个数据向量(Region
),其中包含带有其关联数据模型的URL:
struct URLDataModel {
var url = URL(string: "https://disease.sh/v3/covid-19/apple/countries/Canada")
var dataModel: Any = Region.self
}
以下是整个类,其中包含使用getRegionList()
结构的共享URLDataModel
:
class CountryRegionListModelView: ObservableObject {
@Published var countryRegionList = [String]()
// Data Persistence:
var cancellables: Set<AnyCancellable> = []
// TODO: --- Get Region tag ---
func getRegionList(urlDataModel: URLDataModel) {
// MARK: - Region
struct Country: Codable {
let countries: [String]
}
struct Region: Codable {
let country: String
let subregions: [String]
}
print("url: ",urlDataModel.url)
let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: urlDataModel.url!)
// the dataTaskPublisher output combination is (data: Data,response: URLResponse)
.map(\.data)
.receive(on: DispatchQueue.main)
.print("Hello Data")
.decode(type: urlDataModel.dataModel,decoder: JSONDecoder())
remoteDataPublisher
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
break
case let .failure(anError):
Swift.print("received error: ",anError)
}
},receiveValue: { someValue in
self.countryRegionList = someValue.subregions
print(self.countryRegionList)
}).store(in: &cancellables)
}
}
问题:我不知道如何使JSON解码器与变量模型类型'model'.self 一起使用。
我应该使用泛型吗?
那将如何工作?
解决方法
您可以创建一个协议:
protocol URLResource {
associatedtype DataModel: Decodable
var url: URL? { get }
}
及其示例实现:
struct CovidResource: URLResource {
typealias DataModel = Region
var url = URL(string: "https://disease.sh/v3/covid-19/apple/countries/Canada")
}
然后,您可以使getRegionList
通用并接受 some URLResource:
func getRegionList<Resource>(urlDataModel: Resource) where Resource: URLResource {
let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: resource.url!)
// the dataTaskPublisher output combination is (data: Data,response: URLResponse)
.map(\.data)
.receive(on: DispatchQueue.main)
.decode(type: Resource.DataModel.self,decoder: JSONDecoder())
// ...
}
,
我终于有了这个工作;通过情节提要:
import Combine
import SwiftUI
protocol URLResource {
associatedtype DataModel: Decodable
var url: URL? { get }
}
var cancellables: Set<AnyCancellable> = []
struct CovidResource<T:Decodable>: URLResource {
typealias DataModel = T
var url = URL(string: "https://disease.sh/v3/covid-19/apple/countries/Canada")
}
// MARK: - Canada
struct Canada: Codable {
let country: String
let subregions: [String]
}
let myURL = URL(string: "https://disease.sh/v3/covid-19/apple/countries/Canada")!
func getRegionList<Resource>(urlDataModel: Resource) where Resource: URLResource {
let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: urlDataModel.url!)
.map(\.data)
.receive(on: DispatchQueue.main)
.decode(type: Resource.DataModel.self,decoder: JSONDecoder())
.print("Remote Publisher \(urlDataModel.url!): ")
remoteDataPublisher
.sink(receiveCompletion: { completion in
print(completion)
switch completion {
case .finished:
print("Publisher Finished")
break
case let .failure(anError):
Swift.print("received error: ",anError)
}
},receiveValue: { someValue in
print("someValue: ",someValue)
}).store(in: &cancellables)
}
// ---------------------------------------
let resource = CovidResource<Canada>(url: myURL)
getRegionList(urlDataModel: resource)
print("End of Proof-of-Concept")
print("The End.")
控制台输出:
Remote Publisher https://disease.sh/v3/covid-19/apple/countries/Canada: : receive subscription: (Decode)
Remote Publisher https://disease.sh/v3/covid-19/apple/countries/Canada: : request unlimited
End of Proof-of-Concept
The End.
Remote Publisher https://disease.sh/v3/covid-19/apple/countries/Canada: : receive value: (Canada(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"]))
someValue: Canada(country: "Canada","Yukon Territory"])
Remote Publisher https://disease.sh/v3/covid-19/apple/countries/Canada: : receive finished
finished
Publisher Finished
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。