MVC & MVVM: Implementation of MVVM In RxSwift

RxSwift
Photo by Dimitri Karastelev on Unsplash
Model View Controller
Traditional MVC
MVVM in Swift
public struct TopStoriesResponse : Codable {let results : [Results]}public struct Results : Codable {let title : Stringlet abstract : Stringlet multimedia : [Media]?}public struct Media : Codable {let url : String}
RxSwift MVVM
import Foundationimport RxSwiftimport RxCocoastruct Resource<T:Decodable>{let url : URL}extension URLRequest {static func loadRequest<T>(resource : Resource<T>) -> Observable<T>{return Observable.just(resource.url).flatMap{ url -> Observable<Data> inlet request =  URLRequest(url: url)return URLSession.shared.rx.data(request:request)}.map{ data -> T inreturn try JSONDecoder().decode(T.self, from: data)}}}
struct Resource<T:Decodable>{let url : URL}
extension URLRequest {static func loadRequest<T>(resource : Resource<T>) -> Observable<T>{
return Observable.just(resource.url).flatMap{ url -> Observable<Data> in
let request =  URLRequest(url: url)return URLSession.shared.rx.data(request:request)}
.map{ data -> T inreturn try JSONDecoder().decode(T.self, from: data)}
struct TopStoriesListViewModel {let topStoriesList = PublishSubject<[Results]>()}extension TopStoriesListViewModel {func fetchItems(disposeBag : DisposeBag) {let resource = Resource<TopStoriesResponse>.init(url: URL(string: "https://api.nytimes.com/svc/topstories/v2/home.json?api-key=wZ6nNutGYhiI7LDJQUCTva0k88twlGep")!)URLRequest.loadRequest(resource: resource).subscribe(onNext : { result inlet results = result.resultstopStoriesList.onNext(results)topStoriesList.onCompleted()}).disposed(by: disposeBag)}}
struct TopStoriesListViewModel {let topStoriesList = PublishSubject<[Results]>()}
extension TopStoriesListViewModel {func fetchItems(disposeBag : DisposeBag) {let resource = Resource<TopStoriesResponse>.init(url: URL(string: "https://api.nytimes.com/svc/topstories/v2/home.json?api-key=wZ6nNutGYhiI7LDJQUCTva0k88twlGep")!)
URLRequest.loadRequest(resource: resource).subscribe(onNext : { result in
let results = result.resultstopStoriesList.onNext(results)topStoriesList.onCompleted()}).disposed(by: disposeBag)}}
////  ViewController.swift//  RxNewYorkTimes////  Created by omair khan on 15/12/2021.//import UIKitimport SDWebImageimport RxSwiftimport RxCocoaclass ViewController: UIViewController {// TableViewprivate let tableView: UITableView = {let tableView = UITableView()tableView.register(TopNewsTableViewCell.self, forCellReuseIdentifier: "cell")tableView.translatesAutoresizingMaskIntoConstraints = falsereturn tableView}()let disposeBag = DisposeBag()private var viewModel = TopStoriesListViewModel()override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.title = "Top Stories"setUpTableView()populateData()}// MARK: TableView setupfunc setUpTableView(){/*- Add as Subview- Add constraints- tableView Row Height*/self.view.addSubview(tableView)self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: (self.navigationController?.navigationBar.frame.height)!).isActive = trueself.tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = trueself.tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = trueself.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = truetableView.rowHeight = 150}//MARK: Populate Datafunc populateData(){// fetch itemsself.viewModel.fetchItems(disposeBag: disposeBag)// Bind Dataself.viewModel.topStoriesList.bind(to: self.tableView.rx.items(cellIdentifier: "cell", cellType: TopNewsTableViewCell.self)){ row,item,cell incell.abbstractLabel.text = item.abstractcell.titleLabel.text = item.titlecell.myImageView.sd_setImage(with: URL(string: item.multimedia?[0].url ?? ""), placeholderImage: UIImage(named: "NY"), options: .continueInBackground, completed: nil)}}}
let disposeBag = DisposeBag()private var viewModel = TopStoriesListViewModel()
func populateData(){// fetch itemsself.viewModel.fetchItems(disposeBag: disposeBag)
self.viewModel.topStoriesList.bind(to: self.tableView.rx.items(cellIdentifier: "cell", cellType: TopNewsTableViewCell.self)){ row,item,cell in
cell.abbstractLabel.text = item.abstractcell.titleLabel.text = item.titlecell.myImageView.sd_setImage(with: URL(string: item.multimedia?[0].url ?? ""), placeholderImage: UIImage(named: "NY"), options: .continueInBackground, completed: nil)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store