web-dev-qa-db-fra.com

le type X non nominal ne prend pas en charge l'initialisation explicite

J'essaie de comprendre ce que je fais mal avec les génériques dans Swift.

J'ai créé cet exemple de terrain de jeu

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()
    }
}

la ligne self.c = C(modelView: m) me donne cette erreur non-nominal type 'C' does not support explicit initialization

De cet autre débordement de pile question Je vois que cette erreur dans les anciennes versions de Xcode signifie

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

Mais dans l'aire de jeux ci-dessus, qu'est-ce qui manque au compilateur?

Je suis sur Swift4/xcode9.

Mise à jour

Après avoir suivi la suggestion Use C.init(modelView: m) rather than C(modelView: m) l'erreur change dans:

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

Than @ vini-app a suggéré de supprimer l'UIViewController pour le faire fonctionner. Par je ne comprends toujours pas pourquoi le compilateur n'est pas content quand UIViewController est là. N'est-ce pas suffisant de savoir que C a cette méthode d'initialisation valide?

23
Luca Bartoletti

Il vous suffit d'utiliser explicitement init chaque fois que vous initialisez un paramètre générique plutôt qu'un type "réel":

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

Utilisez C.init(modelView: m) plutôt que C(modelView: m). Cela devrait le réparer.

3
rounak

Vérifiez s'il vous plaît :

Dans votre code, vous faites comme ceci C : MainViewControllerInterface, C : UIViewController.

Il traite C comme ViewController, puis il n'y a pas de init dans ViewController comme init(modelView: M) c'est pourquoi son erreur de lancement

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()
    }
}
1
Vini App