Combine - 如果在线获取失败,如何继续解码本地 json 文件?
Combine - how to proceed to decode a local json file if online fetch failed?
我的 Xcode 工作区中有一个在线托管的最新 json 文件和一个本地 json 文件。如果获取失败,我想继续解码本地存储的文件:MyError.fetchError
例如没有互联网连接。这是管道:
func fetchAndDecode<T: Decodable>(url: URL) -> AnyPublisher<T, MyError> {
fetchURL(url: url)
.decode(type: T.self, decoder: JSONDecoder())
.mapError { error in
if let error = error as? DecodingError {
return MyError.parsingError
} else {
return MyError.fetchError //here somehow proceed to parse local json file
}
}
.eraseToAnyPublisher()
}
如何实现?
.mapError
是错误的运算符,因为它只考虑 Error
分支。
fetchURL
returns 显然Data
,所以在解码数据之前你必须用本地数据替换获取错误。
在 .decode...
行之前插入
.replaceError(with: try! Data(contentsOf: Bundle.main.url(forResource: "local", withExtension: "json")!))
并删除 .mapError
运算符。
local.json
表示bundle中本地文件的文件名。
我可以使用为 iOS 15.
引入的 async
函数提出替代但类似的方法来下载数据和处理错误
创建一个异步读取数据的函数,如果连接有效,return从服务器读取数据,否则如果发现问题,它将 return 本地 JSON :
func getData(fromURL url: URL) async -> Data {
let request = URLRequest(url: url)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("HTTP response: \(response.debugDescription)")
// Found an issue: return the local JSON
return localJSON
}
// If everything is OK, return the data from the server
return data
}
解码数据returned:
// Use the code below in an asynchronous environment -
// either an async function or inside a Task { } closure
let data = await getData(fromURL: url)
do {
let decoded = try JSONDecoder().decode(T.self, from: data)
print("Decoded JSON: \(decoded)")
return decoded
} catch {
print("Error decoding JSON: \(error), \(error.localizedDescription)")
}
我的 Xcode 工作区中有一个在线托管的最新 json 文件和一个本地 json 文件。如果获取失败,我想继续解码本地存储的文件:MyError.fetchError
例如没有互联网连接。这是管道:
func fetchAndDecode<T: Decodable>(url: URL) -> AnyPublisher<T, MyError> {
fetchURL(url: url)
.decode(type: T.self, decoder: JSONDecoder())
.mapError { error in
if let error = error as? DecodingError {
return MyError.parsingError
} else {
return MyError.fetchError //here somehow proceed to parse local json file
}
}
.eraseToAnyPublisher()
}
如何实现?
.mapError
是错误的运算符,因为它只考虑 Error
分支。
fetchURL
returns 显然Data
,所以在解码数据之前你必须用本地数据替换获取错误。
在 .decode...
行之前插入
.replaceError(with: try! Data(contentsOf: Bundle.main.url(forResource: "local", withExtension: "json")!))
并删除 .mapError
运算符。
local.json
表示bundle中本地文件的文件名。
我可以使用为 iOS 15.
引入的async
函数提出替代但类似的方法来下载数据和处理错误
创建一个异步读取数据的函数,如果连接有效,return从服务器读取数据,否则如果发现问题,它将 return 本地 JSON :
func getData(fromURL url: URL) async -> Data {
let request = URLRequest(url: url)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("HTTP response: \(response.debugDescription)")
// Found an issue: return the local JSON
return localJSON
}
// If everything is OK, return the data from the server
return data
}
解码数据returned:
// Use the code below in an asynchronous environment -
// either an async function or inside a Task { } closure
let data = await getData(fromURL: url)
do {
let decoded = try JSONDecoder().decode(T.self, from: data)
print("Decoded JSON: \(decoded)")
return decoded
} catch {
print("Error decoding JSON: \(error), \(error.localizedDescription)")
}