0

I have two UIView and I want to add detailsView as subview with other view. I am getting following error:

Cannot convert value of type 'MovieDetailsDisplayViewController.detailsView.Type' to expected argument type 'MovieDetailsDisplayViewController.View'

View model code ..

enum MoviesDetailsViewModelState { case loading(Movie) case loaded(MovieDetails) case pageLoaded(Page<Movie>) case error var title: String? { switch self { case .loaded(let movie): return movie.title case .loading(let movie): return movie.title case .error: return nil case .pageLoaded: return nil } } var movie: MovieDetails? { switch self { case .loaded(let movie): return movie case .loading, .error: return nil case .pageLoaded: return nil } } var page: Page<Movie>? { switch self { case .loading, .error, .loaded: return nil case .pageLoaded(let page): return page } } } final class MoviesDetailsViewModel { private let apiManager: APIManaging private let initialMovie: Movie var moviePage = [Movie]() init(movie: Movie, apiManager: APIManaging = APIManager()) { self.initialMovie = movie self.apiManager = apiManager self.state = .loading(movie) } var updatedState: (() -> Void)? var state: MoviesDetailsViewModelState { didSet { updatedState?() } } func fetchData() { apiManager.execute(MovieDetails.details(for: initialMovie)) { [weak self] result in guard let self = self else { return } switch result { case .success(let movieDetails): self.state = .loaded(movieDetails) case .failure: self.state = .error } } } func fetchSimilarMovie() { apiManager.execute(Movie.similiar(for: initialMovie.id)) { [weak self] result in guard let self = self else { return } switch result { case.success(let page): self.state = .pageLoaded(page) self.moviePage = page.results print(moviePage) case .failure(let error): self.state = .error print(error) } } } } 

Here is the code for both views:

 final class MovieDetailsDisplayViewController: UIViewController { let movieDetails: MovieDetails init(movieDetails: MovieDetails) { self.movieDetails = movieDetails super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func loadView() { view = ParentView() view = DetailsView(coder: <#NSCoder#>) } override func viewDidLoad() { super.viewDidLoad() (view as? ParentView)?.configure(movieDetails: movieDetails) view.addSubview(DetailsView) } private class ParentView: UIView { let scrollView = UIScrollView() let backdropImageView = UIImageView() let titleLabel = UILabel() let overviewLabel = UILabel() let similarLabel = UILabel() private lazy var contentStackView = UIStackView(arrangedSubviews: [backdropImageView, titleLabel, overviewLabel, similarLabel]) override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit() { backgroundColor = .white backdropImageView.contentMode = .scaleAspectFill backdropImageView.clipsToBounds = true titleLabel.font = UIFont.Heading.medium titleLabel.textColor = UIColor.Text.charcoal titleLabel.numberOfLines = 0 titleLabel.lineBreakMode = .byWordWrapping titleLabel.setContentHuggingPriority(.required, for: .vertical) overviewLabel.font = UIFont.Body.small overviewLabel.textColor = UIColor.Text.grey overviewLabel.numberOfLines = 0 overviewLabel.lineBreakMode = .byWordWrapping similarLabel.font = UIFont.Body.smallSemiBold similarLabel.textColor = UIColor.Text.charcoal similarLabel.numberOfLines = 0 similarLabel.lineBreakMode = .byWordWrapping contentStackView.axis = .vertical contentStackView.spacing = 24 contentStackView.setCustomSpacing(8, after: titleLabel) setupViewsHierarchy() setupConstraints() } private func setupViewsHierarchy() { addSubview(scrollView) scrollView.addSubview(contentStackView) } private func setupConstraints() { scrollView.translatesAutoresizingMaskIntoConstraints = false backdropImageView.translatesAutoresizingMaskIntoConstraints = false contentStackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate( [ scrollView.topAnchor.constraint(equalTo: topAnchor), scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), scrollView.bottomAnchor.constraint(equalTo: bottomAnchor), scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), backdropImageView.heightAnchor.constraint(equalTo: backdropImageView.widthAnchor, multiplier: 11 / 16, constant: 0), contentStackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 24), contentStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), contentStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16), contentStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -24) ] ) scrollView.layoutMargins = UIEdgeInsets(top: 24, left: 16, bottom: 24, right: 16) preservesSuperviewLayoutMargins = false } func configure(movieDetails: MovieDetails) { backdropImageView.dm_setImage(backdropPath: movieDetails.backdropPath) titleLabel.text = movieDetails.title overviewLabel.text = movieDetails.overview } } private class DetailsView: UIView, UICollectionViewDataSource, UICollectionViewDelegate { let viewModel: MoviesDetailsViewModel init(viewModel: MoviesDetailsViewModel) { self.viewModel = viewModel super.init() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } fileprivate let collectionView:UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(SimilierMovieCell.self, forCellWithReuseIdentifier: "CompanyCell") cv.backgroundColor = .lightGray return cv }() private func setUpUI() { addSubview(collectionView) //Add constraint collectionView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true collectionView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true collectionView.topAnchor.constraint(equalTo: topAnchor).isActive = true collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/2.5, height: collectionView.frame.width/2) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { let items = viewModel.moviePage.count return items } 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() } } } 

Here is the screenshot of the error.

enter image description here

11
  • ok . How I needs to create instance of the DetailsView ? Commented Feb 23, 2024 at 23:23
  • Delete your loadView method. In viewDidLoad create an instance of ParentView and DetailView. Add them as subviews of self.view. Commented Feb 24, 2024 at 0:00
  • Please share the code I am still having same error Commented Feb 24, 2024 at 0:05
  • var view = ParentView() var dview = DetailsView(viewModel: viewModel) self.view.addSubview(DetailsView) Commented Feb 24, 2024 at 0:06
  • self.view.addSubview(dview). Commented Feb 24, 2024 at 0:12

2 Answers 2

0

You report this error:

Cannot convert value of type 'MovieDetailsDisplayViewController.detailsView.Type' to expected argument type 'MovieDetailsDisplayViewController.View'

That is a result of the line that says:

view.addSubview(DetailsView) 

DetailsView is the name of a type. But you need to set it to be an instance of the UIView type:

let movie = … let viewModel = MoviesDetailsViewModel(movie: movie) let detailsView = DetailsView(viewModel: viewModel) view.addSubview(detailsView) 

You have not shared where this Movie parameter of the MoviesDetailsViewModel comes from. Perhaps the movieDetails property?

Sign up to request clarification or add additional context in comments.

3 Comments

yes . It take the parameters as well . let me add the code as well .
I am trying to help you, but there are just so many different problems here! There is too much code already, and with every problem we fix, we're going to just hit the next problem, and then next problem, etc. You really should ask a single question per Stack Overflow post. And we don't want to see the gory details, but rather just a simple MRE. There is just too much here and so much that needs refactoring.
can you please look at this question . I have setup the constrains correctly but I do not know why it not showing the view content. Thanks. stackoverflow.com/questions/78066759/…
0

It's a bit hard to follow your code, but the line that is giving the error is wrong. It reads View.addSubview(detailsView). The bit View is your View class, not your current view controller's content view. It should probably read view.addSubview(detailsView) (with view in lower case.)

(Swift is case-sensitive, and View refers to your UIView class, where view in a view controller is shorthand for self.view, or a reference to the view controller's content view.)

8 Comments

By the way, I would advise against having a subclass of UIView named View. SwiftUI uses a View type extensively, and many people reading your code will think that's what you are referencing.
with view.addSubview(detailsView) , it show this error ..Cannot convert value of type 'MovieDetailsDisplayViewController.detailsView.Type' to expected argument type 'UIView'
I have rename it View to parentView still same problem
Gak. It looks like detailsView is a class type rather than an instance of a class. That's why that is giving you an error. Swift has a strong convention of using upper-case names for class and type names, and lower case variables for variable names. You should rename your class as DetailsView, and then you need to create an instance of that type if you want to install it as a subview of your content view.
You have multiple typing problems with your code. You should clean up your naming to follow language conventions.
|