我想发出警报以在 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
此表达式将采用 Bool
、String
值,这两个值都是决定是否显示警报所必需的。
- Bool - 表示网络调用是否成功的值(
true
= 成功,false
= 一些中断)。
- 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
}
}
}
我在 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
此表达式将采用 Bool
、String
值,这两个值都是决定是否显示警报所必需的。
- Bool - 表示网络调用是否成功的值(
true
= 成功,false
= 一些中断)。 - 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
}
}
}