non-nominal type X does not support explicit initialization

15,340

Solution 1

You just need to use init explicitly whenever you're initializing a generic parameter rather than a "real" type:

self.c = C.init(modelView: m)

Solution 2

Use C.init(modelView: m) rather than C(modelView: m). That should fix it.

Solution 3

Please check :

In your code you are doing like this C : MainViewControllerInterface, C : UIViewController.

It is treating C as ViewController, then there is no init in ViewController like init(modelView: M) thats why its throwing error

public class Other<C, M> : NSObject where C : MainViewControllerInterface, M : MainControllerToModelInterface, C.MODELVIEW == M {
    var c : C?

    override init() {
        let m = M()
        self.c = C(modelView: m)
        super.init()
    }
}
Share:
15,340
Luca Bartoletti
Author by

Luca Bartoletti

Updated on June 04, 2022

Comments

  • Luca Bartoletti
    Luca Bartoletti almost 2 years

    I'm trying to understand what I'm doing wrong with generics in swift.

    I created this sample playground

    import UIKit
    
    public protocol MainControllerToModelInterface : class {
        func addGoal()
        init()
    }
    
    public protocol MainViewControllerInterface : class {
        associatedtype MODELVIEW
        var modelView: MODELVIEW? {get set}
    
        init(modelView: MODELVIEW)
    }
    
    public class MainViewController<M> : UIViewController, MainViewControllerInterface where M : MainControllerToModelInterface {
        public weak var modelView: M?
    
        required public init(modelView: M) {
            self.modelView = modelView
            super.init(nibName: String(describing: MainViewController.self), bundle: Bundle.main)
        }
    
        required public init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    public class Other<C, M> : NSObject where C : MainViewControllerInterface, C : UIViewController, M : MainControllerToModelInterface, C.MODELVIEW == M {
        var c : C?
    
        override init() {
            let m = M()
            self.c = C(modelView: m)
            super.init()
        }
    }
    

    the line self.c = C(modelView: m) gives me this error non-nominal type 'C' does not support explicit initialization

    From this other stack overflow question I see that this error in older Xcode versions means

    cannot invoke initializer for type '%type' with an argument list of type '...' expected an argument list of type '...'

    But in the playground above what is the compiler missing?

    I'm on swift4/xcode9.

    Update

    After following the suggestion Use C.init(modelView: m) rather than C(modelView: m) the error changes in:

    No 'C.Type.init' candidates produce the expected contextual result type '_?'

    Than @vini-app suggested to remove the UIViewController to make it works. By I still don't understand why the compiler is not happy when UIViewController is there. Is it not enough to know that C has that valid init method?