Combine-如果在线获取失败,如何继续解码本地json文件



我有一个在线托管的最新json文件和一个Xcode工作区中的本地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显然返回Data,因此在解码数据之前,必须用本地数据替换获取错误。

.decode...行之前插入

.replaceError(with: try! Data(contentsOf: Bundle.main.url(forResource: "local", withExtension: "json")!))

并删除CCD_ 7运算符。

local.json表示捆绑包中本地文件的文件名。

我可以提出一种替代但类似的方法来下载数据并处理错误,使用为iOS 15引入的async功能。

创建一个异步读取数据的函数,如果连接正常,则从服务器返回数据,否则,如果发现问题,则返回本地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
}

解码返回的数据:

// 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)")
}

最新更新