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?
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)
Utilisez C.init(modelView: m)
plutôt que C(modelView: m)
. Cela devrait le réparer.
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()
}
}