Error -> init(coder:) has not been implemented

I'm trying to access another class in my CollectionView Controller but when I try and initialise the class I get the error

Here is the class

@MainActor
class AlbumsViewModel {

    private let albumService: AlbumService
    private let favouritesService: FavouritesService
    private let recommendationService: RecommendationService

    @Published var favourites = [Bool]()
    @Published var recommendedAlbums = [Album]()
    @Published var allAlbums = [Album]() {

        didSet {
            updateFavourites()
        }

    }

    init(albumService: AlbumService, favouritesService: FavouritesService, recommendationService: RecommendationService) {

        self.albumService = albumService
        self.favouritesService = favouritesService
        self.recommendationService = recommendationService

    }
...(functions here)

Collectionview Controller Class

class CVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    var viewModel: AlbumsViewModel

    init?(viewModel: AlbumsViewModel, coder: NSCoder) {
        self.viewModel = viewModel

        super.init(coder: coder)
    }

    required init?(coder: NSCoder) {

        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.delaysContentTouches = false

        Task {
            print(viewModel.allAlbums)
        }


    } // End viewDidLoad
...

Trying to recreate this https://martinmitrevski.com/2021/07/11/ml-recommendation-app-with-create-ml-on-ios-15/

  • Where is the error... which class, which line?

  • The error is in the the collection view class at required init?(coder: NSCoder) {         fatalError("init(coder:) has not been implemented")     }

  • How are you initializing the CVC?

Accepted Reply

You are instantiating the CVC directly from your Storyboard.
So you can't pass in the viewModel property.

You will have to think of another way to use viewModel in CVC. For example, as a global singleton, like this...

In AlbumsViewModel:

static let shared = AlbumsViewModel(albumService:favouritesService:recommendationService:) // however you initialise it

...then in CVC, refer to

AlbumsViewModel.shared

...or create a shortcut property

let viewModel = AlbumsViewModel.shared
  • If I do that I'm not sure what to set albumService, favouritesService and recommendationService as because they are protocols with functions. In the example there is no initialisation for viewModel, how would that work? https://github.com/martinmitrevski/MLRecommendation/blob/master/MLRecommendation/AlbumsView.swift

  • Nevermind the app is in SwiftUI which I'm not really familiar with and the viewModel initialisation was in another file. It was supposed to be initialised like this             `let albumService = LocalAlbumService()   let favoritesService = LocalFavoritesService() let recommendationService = MLRecommendationService()

                AlbumsView(viewModel: AlbumsViewModel(albumService: albumService, favoritesService: favoritesService, recommendationService: recommendationService))`

Add a Comment

Replies

You have defined CVC init(coder:) to throw a fatal error.

You don't show where you are initializing the CVC... ...but it seems that init(coder:) is being called, since you are seeing the error.

You need to implement a proper init(coder:)...

required init?(coder: NSCoder) {
    super.init(coder: coder)
    /// any other setup action here... what about viewModel?
}

... or use your custom initializer instead.

  • I don't have any initialisations other than the one I've shown (Sorry still relatively new). So if I implement that I get the error Property 'self.viewModel' not initialized at super.init call If I add viewModel there what should it be set to?

  • You have not shown an initialization of CVC. Maybe it in initialized using a Storyboard segue? In that case, you could make viewModel an Optional, and set it in the prepare for segue method.

  • Not sure how I should be initialising the CollectionView Controller? With viewModel there isn’t really anything to set in CVC I just need to call the functions from that class. It’s used like this but I don’t see any initialisation used here

You should add at least super.init and remove fatal error.

What I often do is define a sharedInit() func that I call in all init, including coder.

        self.sharedInit()  

You are instantiating the CVC directly from your Storyboard.
So you can't pass in the viewModel property.

You will have to think of another way to use viewModel in CVC. For example, as a global singleton, like this...

In AlbumsViewModel:

static let shared = AlbumsViewModel(albumService:favouritesService:recommendationService:) // however you initialise it

...then in CVC, refer to

AlbumsViewModel.shared

...or create a shortcut property

let viewModel = AlbumsViewModel.shared
  • If I do that I'm not sure what to set albumService, favouritesService and recommendationService as because they are protocols with functions. In the example there is no initialisation for viewModel, how would that work? https://github.com/martinmitrevski/MLRecommendation/blob/master/MLRecommendation/AlbumsView.swift

  • Nevermind the app is in SwiftUI which I'm not really familiar with and the viewModel initialisation was in another file. It was supposed to be initialised like this             `let albumService = LocalAlbumService()   let favoritesService = LocalFavoritesService() let recommendationService = MLRecommendationService()

                AlbumsView(viewModel: AlbumsViewModel(albumService: albumService, favoritesService: favoritesService, recommendationService: recommendationService))`

Add a Comment