I have a flow where I should get posts from web, and save them on user defaults as test, if there is some issue, load the list from users default instead from web. now I have two emitters, I think I should perform a check in my repository, something like if gateposts emits error, put to the error decide to show local cached posts. How to catch the error? they told me I could use combine latest or mergeMany but Im totally new and have no idea how to perform this check
I have this hint, but is not working
dataSource.getPosts().catch {sharedPreferenceDataSource.getLocalPosts()}
this seems to work, but still not getting with error or using combine latest
return dataSource.getPosts().catch { error in
return self.sharedPreferenceDataSource.getLocalPosts()
}.eraseToAnyPublisher()
my func
func getPosts() -> AnyPublisher<[Post], Error> {
//posts from web
dataSource.getPosts() //emits AnyPublisher<[Post], Error>
//posts on usersDeafault
sharedPreferenceDataSource.getLocalPosts() //emits AnyPublisher<[Post], Error>
//here someone told me I should perform a catch,I get something likeMyEnumeError.networkError, then I should emit local posts
//my latest attempt
return Publishers.CombineLatest(dataSource.getPosts(), sharedPreferenceDataSource.getLocalPosts())
// but I think I could do something like
// perform a catch on the error from network, in that case perform a catch and send local data
// Publishers.MergeMany([dataSource.getPosts(),dataSource.getLocalPosts(defaults: defaults, key: UserDefaultKeys.allPost.rawValue)])
}
my call
enum NetworkError: Error {
case genericError(code: Int)
case invalidResponseCode
case decodingFailure(reason: String)
}
func getPosts() -> AnyPublisher<[Post], Error> {
let session = URLSession.shared
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
return Future<[Post], Error>() { promise in
//***********************************************
let task = session.dataTask(with: url, completionHandler: { data, response, error in
if error != nil {
print(error ?? "N/D")
promise(Result.failure(NetworkError.invalidResponseCode))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
promise(Result.failure(NetworkError.invalidResponseCode))
return
}
do {
let posts = try JSONDecoder().decode([Post].self, from: data! )
promise(Result.success(posts))
//saving on local disk
self.saveLocalPosts(defaults: self.defaults, data: AllPosts(Posts: posts))
} catch {
print("Error during JSON serialization: \(error.localizedDescription)")
promise(Result.failure(NetworkError.decodingFailure(reason: error.localizedDescription)))
}
})
task.resume()
//***********************************************
}
// .receive(on: DispatchQueue.main)
// .subscribe(on: DispatchQueue.init(label: "test", qos: .default))
// .map { value -> [Post] in
// let c = value
// return []
// }
.eraseToAnyPublisher()
}