I making an attempt to configure the information is obtain from API name. I’ve debug the community name and I can see on debug console I’ve obtain the information into view mannequin . I have no idea why it not configure the gathering view cell. I used to be instructed by SO neighborhood person to replace UI based mostly on asynchronous name . Nonetheless identical end result.
Right here is the view Mannequin code ..
enum MoviesDetailsViewModelState {
case loading(Film)
case loaded(MovieDetails)
case pageLoaded(Web page<Film>)
case error
var web page: Web page<Film>? {
swap self {
case .loading, .error, .loaded:
return nil
case .pageLoaded(let web page):
return web page
}
}
}
closing class MoviesDetailsViewModel {
non-public let apiManager: APIManaging
non-public let initialMovie: Film
var moviePage = [Movie]()
init(film: Film, apiManager: APIManaging = APIManager()) {
self.initialMovie = film
self.apiManager = apiManager
self.state = .loading(film)
}
var updatedState: (() -> Void)?
var state: MoviesDetailsViewModelState {
didSet {
updatedState?()
}
}
func fetchSimilarMovie() {
apiManager.execute(Film.similiar(for: initialMovie.id)) { [weak self] lead to
guard let self = self else { return }
swap end result {
case.success(let web page):
self.state = .pageLoaded(web page)
self.moviePage = web page.outcomes
print(moviePage)
case .failure(let error):
self.state = .error
print(error)
}
}
}
}
Right here is the debug end result ..
Right here is the view controller code ..
class SmiliarMovieViewController: UIViewController, UICollectionViewDelegate {
non-public let viewModel: MoviesDetailsViewModel
init(viewModel: MoviesDetailsViewModel) {
self.viewModel = viewModel
tremendous.init(nibName: nil, bundle: nil)
navigationItem.largeTitleDisplayMode = .by no means
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been carried out")
}
fileprivate let collectionView: UICollectionView = {
let format = UICollectionViewFlowLayout()
format.scrollDirection = .horizontal
let cv = UICollectionView(body: .zero, collectionViewLayout: format)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.register(SimilierMovieCell.self, forCellWithReuseIdentifier: "CompanyCell")
cv.backgroundColor = .lightGray
return cv
}()
override func viewDidLoad() {
tremendous.viewDidLoad()
setUpUI()
self.viewModel.updatedState = { [weak self] in
DispatchQueue.predominant.async {
self?.collectionView.reloadData()
}
}
viewModel.fetchSimilarMovie()
}
non-public func setUpUI() {
view.addSubview(collectionView)
collectionView.topAnchor.constraint(equalTo: view.topAnchor, fixed: 40).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, fixed: 40).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, fixed: -40).isActive = true
collectionView.heightAnchor.constraint(equalToConstant: view.body.width/2).isActive = true
}
}
extension SmiliarMovieViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, format collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.body.width/2.5, top: collectionView.body.width/2)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection part: Int) -> Int {
let gadgets = viewModel.moviePage.rely
return gadgets
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SimilierMovieCell.identifier, for: indexPath) as? SimilierMovieCell
let listMovie = viewModel.moviePage[indexPath.row]
print(listMovie)
cell?.configure(listMovie)
return cell ?? SimilierMovieCell()
}
}
I’ve refactor the code as par as suggestion. However identical end result.
override func viewDidLoad() {
tremendous.viewDidLoad()
setUpUI()
self.viewModel.updatedState = { [weak self] in
DispatchQueue.predominant.async {
self?.collectionView.reloadData()
}
}
viewModel.fetchSimilarMovie()
}
Right here is the end result .. empty view ..