我正在尝试创建一个应用来从API获取一些新闻,并且我正在使用Moya,RxSwift和MVVM。这是我的ViewModel:
import Foundation
import RxSwift
import RxCocoa
public enum NewsListError {
case internetError(String)
case serverMessage(String)
}
enum ViewModelState {
case success
case failure
}
protocol NewsListViewModelInput {
func viewDidLoad()
func didLoadNextPage()
}
protocol MoviesListViewModelOutput {
var newsList: PublishSubject<NewsList> { get }
var error: PublishSubject<String> { get }
var loading: PublishSubject<Bool> { get }
var isEmpty: PublishSubject<Bool> { get }
}
protocol NewsListViewModel: NewsListViewModelInput, MoviesListViewModelOutput {}
class DefaultNewsListViewModel: NewsListViewModel{
func viewDidLoad() {
}
func didLoadNextPage() {
}
private(set) var currentPage: Int = 0
private var totalPageCount: Int = 1
var hasMorePages: Bool {
return currentPage < totalPageCount
}
var nextPage: Int {
guard hasMorePages else { return currentPage }
return currentPage + 1
}
private var newsLoadTask: Cancellable? { willSet { newsLoadTask?.cancel() } }
private let disposable = DisposeBag()
// MARK: - OUTPUT
let newsList: PublishSubject<NewsList> = PublishSubject()
let error: PublishSubject<String> = PublishSubject()
let loading: PublishSubject<Bool> = PublishSubject()
let isEmpty: PublishSubject<Bool> = PublishSubject()
func getNewsList() -> Void{
print("sono dentro il viewModel!")
NewsDataService.shared.getNewsList()
.subscribe { event in
switch event {
case .next(let progressResponse):
if progressResponse.response != nil {
do{
let json = try progressResponse.response?.map(NewsList.self)
print(json!)
self.newsList.onNext(json!)
}
catch _ {
print("error try")
}
} else {
print("Progress: \(progressResponse.progress)")
}
case .error( _): break
// handle the error
default:
break
}
}
}
}
这是我的ViewController,当我尝试绑定到tableNews时,xCode给我以下错误:
Expression type 'Reactive<_>' is ambiguous without more context
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var tableNews: UITableView!
let viewModel = DefaultNewsListViewModel()
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
}
private func setupBindings() {
viewModel.newsList.bind(to: tableNews.rx.items(cellIdentifier: "Cell")) {
(index, repository: NewsList, cell) in
cell.textLabel?.text = repository.name
cell.detailTextLabel?.text = repository.url
}
.disposed(by: disposeBag)
}
}
这是从API获取数据的服务:
import Moya
import RxSwift
struct NewsDataService {
static let shared = NewsDataService()
private let disposable = DisposeBag()
private init() {}
fileprivate let newsListProvider = MoyaProvider<NewsService>()
func getNewsList() -> Observable<ProgressResponse> {
self.newsListProvider.rx.requestWithProgress(.readNewsList)
}
}
我是rxSwift的新手,我关注了一些文档,但我想知道我是否正在以正确的方式进行工作。我想知道的另一点是如何正确地将tableView绑定到viewModel。感谢您的支持。
如评论中的@FabioFelici所述,UITableView.rx.items(cellIdentifier:)
期望绑定到包含对象数组的Observable,但您的NewsListViewModel.newsList
是Observable<NewsList>
。
这意味着您必须通过地图将数组从NewsList中提取出来(假设它有一个)。如newsList.map { $0.items }.bind(to:
...
此外,您的MoviesListViewModelOutput
不应充满主题,而应包含可观察对象。而且我不会理会这些协议,strut
很好。
此外,您的视图模型仍然非常必要,并不是真正的Rx样式。构造良好的Rx视图模型不包含重复调用的函数。它只有一个构造函数(或者本身只是一个函数。)创建它,绑定到它,然后就完成了。