发生错误时加载行为不会停止

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 逻辑分开