2015-11-17 44 views
9

Sono curioso che ci sia comunque un metodo nel metodo init che imposta le proprietà di istanza della classe . Essenzialmente ho solo una classe che sottovoce UIView, aggiunge alcune sottoview in init e alcune di queste subview sono variabili di istanza della classe.'Uso di self in method call prima che super.init inizializzi self', impossibile inizializzare le proprietà tramite un metodo call

class MyView: UIView { 
    var collectionView: UICollectionView 

    convenience init() { 
     self.init(frame:CGRectZero) 
    } 

    override init (frame : CGRect) { 
     super.init(frame : frame) 

     addSubviews() 
    } 

    required init(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 

     addSubviews() 
    } 

    func addSubviews(){ 
     self.collectionView = UICollectionView() 

    } 
} 

Ora il problema arriva che non riesco a chiamare super-init prima di inizializzare le mie classi proprietà interne (Proprietà 'self.collectionView' non inialized a richiesta super.init), ma anche io non posso chiamare mia abitudine metodo per inizializzare quelle variabili prima di super.init, in quanto non può usare self prima di quell'inizializzazione. Mi rendo conto che potrei rendere facoltativa la variabile di istanza, ma sembra meno elegante, poiché so che sarà sempre inizializzata (e ce ne sono molti altri, questa è solo una versione semplificata). C'è un modo per realizzare questo senza rendere tutte le variabili di istanza optionals?

EDIT:

Credo che in ultima analisi, la mia domanda è perché fa rapidi dis-consentono di chiamare un metodo prima di chiamare super.init? Qual è la differenza tra:

override init (frame : CGRect) { 
    addSubviews() 
    super.init(frame : frame) 
} 

final func addSubviews(){ 
    self.collectionView = UICollectionView() 
} 

e

override init (frame : CGRect) { 
    self.collectionView = UICollectionView() 
    super.init(frame : frame) 
} 
+0

Poiché sai che verranno sempre inizializzate, potresti rendere facoltativamente gli optionals non utilizzati. – Moritz

+0

@EricD. Ecco come lo facevi attualmente, ma mi piace il controllo del tempo di compilazione per assicurarci che li stiamo effettivamente impostando tutti –

+0

dare i valori di default delle proprietà – user3441734

risposta

18

documentazione Forma:

Swift’s compiler performs four helpful safety-checks to make sure that two-phase initialization is completed without error:

Safety check 1 A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

È necessario impostare il valore per la variabile di istanza prima di chiamare super.init() E dopo questa azione accederai ai metodi di istanza di chiamata. Nel tuo caso si può fare questo:

override init (frame : CGRect) { 
    self.collectionView = UICollectionView() 
    super.init(frame : frame) 
    // Now you can call method 
    self.someMethod() 
} 

ADD per la modifica della domanda:

Non è possibile chiamare metodo prima super.init() chiamata a causa di motivi di sicurezza. Se lo farai, il tuo metodo può utilizzare alcune proprietà che non sono ancora state inizializzate nella classe genitore

+1

Sì, l'unico problema che ho con questo, è che il codice dovrebbe essere duplicato tra il coder init e il frame init. Tirare questo in un metodo separato è l'ideale, ma swift non ti permetterà di chiamare un metodo prima di init. –

+0

@KevinDiTraglia Prima di tutto hai già provato a duplicare l'inizializzazione con due volte chiamando questo metodo. E secondo non può farlo in fretta a causa di due regole di inizializzazione di base: tutte le proprietà devono essere introdotte prima di 'super.init()' chiamata e i metodi di istanza possono essere chiamati solo dopo 'super.init()' chiama –

+0

@KevinDiTraglia I modifica risposta –