Reputation: 19
I'm learning how to display data in a tableview through 'the movie db' api using the VIPER architecture but I still haven't learned how to decode and serialize JSON. I share my classes.
The JSON Response
{
"page": 1,
"results": [
{
"adult": false,
"backdrop_path": "/aTovumsNlDjof7YVoU5nW2RHaYn.jpg",
"genre_ids": [
27,
53,
10749
],
"id": 616820,
"original_language": "en",
"original_title": "Halloween Ends",
"overview": "Four years after the events of Halloween in 2018, Laurie has decided to liberate herself from fear and rage and embrace life. But when a young man is accused of killing a boy he was babysitting, it ignites a cascade of violence and terror that will force Laurie to finally confront the evil she can’t control, once and for all.",
"popularity": 4845.496,
"poster_path": "/3uDwqxbr0j34rJVJMOW6o8Upw5W.jpg",
"release_date": "2022-10-12",
"title": "Halloween Ends",
"video": false,
"vote_average": 6.9,
"vote_count": 417
},
{
"adult": false,
"backdrop_path": "/5GA3vV1aWWHTSDO5eno8V5zDo8r.jpg",
"genre_ids": [
27,
53
],
"id": 760161,
"original_language": "en",
"original_title": "Orphan: First Kill",
"overview": "After escaping from an Estonian psychiatric facility, Leena Klammer travels to America by impersonating Esther, the missing daughter of a wealthy family. But when her mask starts to slip, she is put against a mother who will protect her family from the murderous “child” at any cost.",
"popularity": 3138.264,
"poster_path": "/pHkKbIRoCe7zIFvqan9LFSaQAde.jpg",
"release_date": "2022-07-27",
"title": "Orphan: First Kill",
"video": false,
"vote_average": 6.8,
"vote_count": 1046
},
{
"adult": false,
"backdrop_path": "/etP5jwlwvkNhwe7jnI2AyA6ZKrR.jpg",
"genre_ids": [
878
],
"id": 575322,
"original_language": "en",
"original_title": "Звёздный разум",
"overview": "After depleting Earth's resources for centuries, humankind's survival requires an exodus to outer space. An international expedition is quickly formed to find a suitable new planet, but when plans go awry, the crew is suddenly stranded without power on a strange planet, where something unimaginable lies in wait.",
"popularity": 2457.191,
"poster_path": "/aVLV38txajXhEy2qNEClPIsDbAH.jpg",
"release_date": "2022-01-06",
"title": "Project Gemini",
"video": false,
"vote_average": 5.5,
"vote_count": 98
}
],
"total_pages": 35518,
"total_results": 710341
}
InteractorTMDB
import Foundation
protocol AnyInteractor{
var presenter : AnyPresenter? {get set}
func downloadMovies()
}
class MovieInteractor : AnyInteractor {
var presenter : AnyPresenter?
func downloadMovies(){
guard let url = URL(string: "https://api.themoviedb.org/3/movie/popular?api_key=115962553d2044ca5dd8433fb4bc3e29")
else{
return
}
let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard let data = data, error == nil else {
self?.presenter?.interactorDidDownloadMovie(result:
.failure(NetworkError.networkFailed))
return
}
do{
let movies = try JSONDecoder().decode([Result].self, from: data)
self?.presenter?.interactorDidDownloadMovie(result: .success(movies))
}catch{
self?.presenter?.interactorDidDownloadMovie(result: .failure(NetworkError.parsingFailed))
}
}
task.resume()
}
}
PresenterTMDB
import Foundation
enum NetworkError : Error {
case networkFailed
case parsingFailed
}
protocol AnyPresenter {
var router : AnyRouter? {get set}
var interactor : AnyInteractor? {get set}
var view : AnyView? {get set}
func interactorDidDownloadMovie(result: Result<Movies: [Results], Error>)
}
class MoviePresenter : AnyPresenter {
var router: AnyRouter?
var interactor : AnyInteractor? {
didSet{
interactor?.downloadMovies()
}
}
var view: AnyView?
func interactorDidDownloadMovie(result: Result<Movies: [Results], Error>){
switch result{
case .success(let movies):
view?.update(with: movies)
case.failure(_):
view?.update(with: "Intenta más tarde")
}
}
}
EntityTMDB
import Foundation
struct Movies: Codable {
let page: Int
let results: [Results]
let totalPages, totalResults: Int
}
struct Results: Codable {
let adult: Bool
let backdropPath: String
let genreIDS: [Int]
let id: Int
let originalTitle, overview: String
let popularity: Double
let posterPath, releaseDate, title: String
let video: Bool
let voteAverage: Double
let voteCount: Int
}
RouterTMDB
import Foundation
import UIKit
typealias EntryPoint = AnyView & UIViewController
protocol AnyRouter{
var entry: EntryPoint? {get}
static func startExecution() -> AnyRouter
}
class MovieRouter : AnyRouter {
var entry : EntryPoint?
static func startExecution() -> AnyRouter {
let router = MovieRouter()
var view: AnyView = ViewTMDB() as! AnyView
var presenter : AnyPresenter = MoviePresenter()
var interactor : AnyInteractor = MovieInteractor()
view.presenter = presenter
presenter.view = view
presenter.router = router
presenter.interactor = interactor
interactor.presenter = presenter
router.entry = view as? EntryPoint
return router
}
}
I really don't know how to show this JSON response in a tableview using VIPER architecture.
Thanks.
Upvotes: -2
Views: 134
Reputation: 131481
Take a look at the Codable
protocol. For deserializing objects from JSON you'll specifically want the Decodable
protocol.
There are simple steps you take to make your structures conform to the Decodable protocol, and then you use an instance of the JSONDecoder
class to decode your object.
How to display your data in a table view, using VIPER or not, is a separate question. (And I would suggest running away from VIPER as fast as you can. It isn't a design pattern I recommend.)
Upvotes: -1