发生错误时加载行为不会停止
loading behavior do not stop when error occur
我使用 Alamofire 创建了一个通用函数
这是函数
class APIServices {
private init() {}
static let instance = APIServices()
func getData<T: Decodable, E: Decodable>(url: String, method: HTTPMethod ,params: Parameters?, encoding: ParameterEncoding ,headers: HTTPHeaders? ,completion: @escaping (T?, E?, Error?)->()) {
AF.request(url, method: method, parameters: params, encoding: encoding, headers: headers)
.validate(statusCode: 200...300)
.responseJSON { (response) in
switch response.result {
case .success(_):
guard let data = response.data else { return }
do {
let jsonData = try JSONDecoder().decode(T.self, from: data)
completion(jsonData, nil, nil)
} catch let jsonError {
print(jsonError)
}
case .failure(let error):
// switch on Error Status Code
guard let data = response.data else { return }
guard let statusCode = response.response?.statusCode else { return }
switch statusCode {
case 400..<500:
do {
let jsonError = try JSONDecoder().decode(E.self, from: data)
completion(nil, jsonError, nil)
} catch let jsonError {
print(jsonError)
}
default:
completion(nil, nil, error)
}
}
}
}
}
并在 HomeViewModel 中使用它
class HomeViewModel {
var loadingBehavior = BehaviorRelay<Bool>(value: false)
private var homeModelSubject = PublishSubject<[Book]>()
private var isTableHidden = BehaviorRelay<Bool>(value: false)
var homeModelObservable: Observable<[Book]> {
return homeModelSubject
}
var isTableHiddenObservable:Observable<Bool> {
return isTableHidden.asObservable()
}
func getBooks(handler: @escaping networkHandler) {
loadingBehavior.accept(true)
let url = "https://simple-books-api.glitch.me/books"
APIServices.instance.getData(url: url, method: .get, params: nil, encoding: JSONEncoding.default, headers: nil) {[weak self] (bookModel: [Book]?, baseError: HomeBaseError?, error) in
guard let self = self else { return }
self.loadingBehavior.accept(false)
if let error = error {
print("this is error discription\(error.localizedDescription)")
} else if let baseError = baseError {
print(baseError.error)
} else {
guard let bookModel = bookModel else { return }
if bookModel.count > 0 {
self.homeModelSubject.onNext(bookModel)
self.isTableHidden.accept(false)
} else {
self.isTableHidden.accept(true)
}
}
}
}
}
问题是当关闭 wifi 加载时不停止也不打印 error.localizedDescription 并且当我进行调试时不要转到 if let error ...
很难理解究竟出了什么问题,但我建议您移除(至少?)4 个您不使用完成处理程序的明显错误。
第一个是
guard let data = response.data else { return }
这应该改为
guard let data = response.data else {
completion(nil, nil, nil)
return
}
或者如果您认为这是一个错误,您可能需要像
这样的东西
guard let data = response.data else {
completion(nil, nil, NoDataError())
return
}
其中 NoDataError 是您需要创建的自定义错误。您需要在两个地方修复此问题。
另一种情况是解码错误(也是两处)
} catch let jsonError {
print(jsonError)
}
在这里你也应该使用你的完成处理程序
} catch let jsonError {
print(jsonError)
completion(nil, nil, jsonError)
}
您在收到错误(失败)时也有一个逻辑错误,因为您在解码之前正在检查 http 状态代码,但如果您的状态代码 > 200,您将永远不会得到响应
所以当你得到一个 .failure
你应该只解码错误,你拥有的整个响应状态逻辑需要与你的 success/failure 逻辑分开
我使用 Alamofire 创建了一个通用函数
这是函数
class APIServices {
private init() {}
static let instance = APIServices()
func getData<T: Decodable, E: Decodable>(url: String, method: HTTPMethod ,params: Parameters?, encoding: ParameterEncoding ,headers: HTTPHeaders? ,completion: @escaping (T?, E?, Error?)->()) {
AF.request(url, method: method, parameters: params, encoding: encoding, headers: headers)
.validate(statusCode: 200...300)
.responseJSON { (response) in
switch response.result {
case .success(_):
guard let data = response.data else { return }
do {
let jsonData = try JSONDecoder().decode(T.self, from: data)
completion(jsonData, nil, nil)
} catch let jsonError {
print(jsonError)
}
case .failure(let error):
// switch on Error Status Code
guard let data = response.data else { return }
guard let statusCode = response.response?.statusCode else { return }
switch statusCode {
case 400..<500:
do {
let jsonError = try JSONDecoder().decode(E.self, from: data)
completion(nil, jsonError, nil)
} catch let jsonError {
print(jsonError)
}
default:
completion(nil, nil, error)
}
}
}
}
}
并在 HomeViewModel 中使用它
class HomeViewModel {
var loadingBehavior = BehaviorRelay<Bool>(value: false)
private var homeModelSubject = PublishSubject<[Book]>()
private var isTableHidden = BehaviorRelay<Bool>(value: false)
var homeModelObservable: Observable<[Book]> {
return homeModelSubject
}
var isTableHiddenObservable:Observable<Bool> {
return isTableHidden.asObservable()
}
func getBooks(handler: @escaping networkHandler) {
loadingBehavior.accept(true)
let url = "https://simple-books-api.glitch.me/books"
APIServices.instance.getData(url: url, method: .get, params: nil, encoding: JSONEncoding.default, headers: nil) {[weak self] (bookModel: [Book]?, baseError: HomeBaseError?, error) in
guard let self = self else { return }
self.loadingBehavior.accept(false)
if let error = error {
print("this is error discription\(error.localizedDescription)")
} else if let baseError = baseError {
print(baseError.error)
} else {
guard let bookModel = bookModel else { return }
if bookModel.count > 0 {
self.homeModelSubject.onNext(bookModel)
self.isTableHidden.accept(false)
} else {
self.isTableHidden.accept(true)
}
}
}
}
}
问题是当关闭 wifi 加载时不停止也不打印 error.localizedDescription 并且当我进行调试时不要转到 if let error ...
很难理解究竟出了什么问题,但我建议您移除(至少?)4 个您不使用完成处理程序的明显错误。
第一个是
guard let data = response.data else { return }
这应该改为
guard let data = response.data else {
completion(nil, nil, nil)
return
}
或者如果您认为这是一个错误,您可能需要像
这样的东西guard let data = response.data else {
completion(nil, nil, NoDataError())
return
}
其中 NoDataError 是您需要创建的自定义错误。您需要在两个地方修复此问题。
另一种情况是解码错误(也是两处)
} catch let jsonError {
print(jsonError)
}
在这里你也应该使用你的完成处理程序
} catch let jsonError {
print(jsonError)
completion(nil, nil, jsonError)
}
您在收到错误(失败)时也有一个逻辑错误,因为您在解码之前正在检查 http 状态代码,但如果您的状态代码 > 200,您将永远不会得到响应
所以当你得到一个 .failure
你应该只解码错误,你拥有的整个响应状态逻辑需要与你的 success/failure 逻辑分开