我想发出警报以在 HomeVC 中显示消息错误

I want to make alert to show message error in HomeVC

我在 HomeViewModel 中有一个函数可以使用 Alamofire 从 api 服务中获取书籍。我希望在发生错误时显示警报以显示用户错误消息

这里是我的 ViewModel..

import Foundation import RxCocoa import RxSwift import Alamofire

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() {
    
    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(error)
            
        } else if let baseError = baseError {
            print(baseError)
            
        } else {
            
            guard let books = bookModel else { return }
            if books.count > 0 {
                
                self.homeModelSubject.onNext(books)
                self.isTableHidden.accept(true)
                
            } else {
                self.isTableHidden.accept(false)
            }
        }
    }
}

}

here my HomeVC import UIKit import RxCocoa import RxSwift

class HomeVC: UIViewController {

let tableView: UITableView = {
    let tableView = UITableView()
    tableView.separatorColor = .clear
    tableView.rowHeight = 140
    tableView.register(HomeTableViewCell.self, forCellReuseIdentifier: HomeTableViewCell.reuseIdentifier)
    return tableView
}()

let homeViewModel = HomeViewModel()
let disposeBage   = DisposeBag()

override func viewDidLoad() {
    super.viewDidLoad()
    configureViewController()
    configureTableView()
    subscribeToLoading()
    subscribeToResponse()
    subscribeToPostSelection()
    getResponse()
    
}

func configureViewController() {
    title = "Home"
    view.backgroundColor = .systemBackground
}

func configureTableView() {
    tableView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(tableView)
    NSLayoutConstraint.activate([
        tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
    ])
}

func subscribeToLoading() {
    homeViewModel.loadingBehavior.subscribe(onNext: { (isLoading) in
        if isLoading {
            self.showIndicator(withTitle: "loading", and: "")
        } else {
            self.hideIndicator()
        }
    }).disposed(by: disposeBage)
}

func subscribeToResponse() {
    homeViewModel.homeModelObservable.bind(to: self.tableView.rx.items(cellIdentifier: HomeTableViewCell.reuseIdentifier, cellType: HomeTableViewCell.self)) { row,books,cell in
        cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: UIScreen.main.bounds.width)
        cell.titleLabel.text            = books.name
        cell.secondaryTitleLabel.text  = books.type
        if books.available == true {
            cell.avalibaleOrNotLabel.text = "Avalibale"
            cell.avalibaleOrNotStatus.backgroundColor = .green
        } else {
            cell.avalibaleOrNotLabel.text = "Not Avalibale"
            cell.avalibaleOrNotStatus.backgroundColor = .gray
        }
        
    }.disposed(by: disposeBage)
}

func subscribeToPostSelection() {
    Observable.zip(tableView.rx.itemSelected,tableView.rx.modelSelected(Book.self)).bind { selectedIndex , post in
        print(selectedIndex)
    }.disposed(by: disposeBage)
}

func getResponse() {
    homeViewModel.getBooks()
}

}

因此您可以在 HomeViewController 中使用 closures 作为回调。让我解释一下。

首先全局定义如下所示的闭包表达式。全局使用它的意义在于您可以在整个应用程序中重复使用相同的表达式。我已将其设置为 typealias 以便于重复使用。

typealias networkHandler = (Bool, String) -> Void

此表达式将采用 BoolString 值,这两个值都是决定是否显示警报所必需的。

  1. Bool - 表示网络调用是否成功的值(true = 成功,false = 一些中断)。
  2. String - 发生错误时显示的字符串消息

然后,将 networkHandler 作为参数添加到 HomeViewModel 中的 getBooks() 方法,如下所示。添加后调用 handler 你觉得会导致错误或网络调用成功的地方。

func getBooks(handler: networkHandler) {
// If the network call was successful
    if success {
        handler(true, "Success")
    }

    // If an error occurs add the handler as follows
    if let error = error {
        handler(false, "Error message\(error.localizedDescription)")
    }
}

添加后,您必须更改 HomeViewController 中的 getResponse() 方法,使其看起来类似于以下内容。 XCode 自动完成将帮助您完成此 XD。


private func getResponse() {
    homeViewModel.getBooks { isSuccessful, message
       if isSuccessful {
           // Do something
           print("successful", message)
       } else {
           // Show the alert message
           showAlert(message: message)   // Define this action as you wish
       }
    }
}