2015-06-12 25 views
8

Sto provando a creare una sottoclasse di UIView in Swift.Ignora init() in un'app di arresto anomalo di CustomUIView (EXC_BAD ACCESS)

Ad ogni modo l'applicazione si blocca (EXC_BAD_ACCESS) quando l'inizializzazione è chiamato

Ecco la classe

class CustomActionSheet: UIView { 
    private var cancelButtonTitle: String!; 
    private var destructiveButtonTitle: String!; 
    private var otherButtonTitles: [String]!; 

    convenience init() { 
     self.init();//EXC_BAD_ACCESS 
    } 

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

    convenience init(cancelButtonTitle: String!, destructiveButtonTitle: String!, otherButtonTitles: [String]!) { 
     self.init(); 


     self.cancelButtonTitle = cancelButtonTitle; 
     self.destructiveButtonTitle = destructiveButtonTitle; 
     self.otherButtonTitles = otherButtonTitles; 

     prepareUI(); 
    } 

    func prepareUI() { 
     //BLABLABLABLABLA 
    } 
} 

Ecco come lo chiamo io

var actionSheet: CustomActionSheet = CustomActionSheet(cancelButtonTitle: "Cancel", destructiveButtonTitle: "OK", otherButtonTitles: nil); 

Tried sostituire self.init() con super.init() ma non co mpile.

messaggio di errore:

devono chiamare un inizializzatore designato della superclasse 'UIView'

Convenienza inizializzatore per 'CustomActionSheet' deve delegare (con 'self.init') piuttosto che al concatenamento inizializzatore di una superclasse (con 'super.init')

+1

Intendevi mettere super.init() nel posto con l'errore? – spektr

+0

super.init() non compilerà nemmeno @choward. Ho aggiornato la mia domanda. – JayVDiyk

risposta

7

È necessario inizializzare UIVIew con un frame, anche se è zero, è inoltre necessario sovrascrivere l'init in modo da poter nitialize le variabili prima chiamata di cena:

class CustomActionSheet: UIView { 
    private var cancelButtonTitle: String!; 
    private var destructiveButtonTitle: String!; 
    private var otherButtonTitles: [String]!; 


    override init(frame: CGRect) { 
     cancelButtonTitle = String() 
     destructiveButtonTitle = String() 
     otherButtonTitles: [String]() 
     super.init(frame:frame) 
    } 

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

    convenience init(cancelButtonTitle: String!, destructiveButtonTitle: String!, otherButtonTitles: [String]!) { 
     self.init(frame: CGRectZero) 
     self.cancelButtonTitle = cancelButtonTitle; 
     self.destructiveButtonTitle = destructiveButtonTitle; 
     self.otherButtonTitles = otherButtonTitles; 
     prepareUI(); 
    } 
} 

Avviso ho rimuovere l'altra convenienza di inizializzazione si creano dato tutte le variabili sono private non v'è alcuna necessità di questo initializer, se si vuole avere un inizializzatore vuoto si può semplicemente aggiungere come:

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

anche la dimensione della cornice può essere passato o fix è sufficiente apportare le modifiche appropriate e chiamare init(frame: yourFrame)

Regole per l'inizializzazione da Apple Documentation:

Regola 1 Un inizializzatore designato deve chiamare un inizializzatore designato dalla sua superclasse immediata.

Regola 2 Un inizializzatore di convenienza deve chiamare un altro inizializzatore da della stessa classe.

Regola 3 Un inizializzatore di convenienza deve infine chiamare un inizializzatore designato .

Un modo semplice per ricordare questo è:

inizializzatori designati devono sempre delegare up. Convenienza Gli inizializzatori devono sempre delegare attraverso.

enter image description here

spero che ti aiuta!

+0

Grazie, funziona – JayVDiyk

+1

Sono contento che funzioni, aggiungerò un po 'di dettagli in più Ho anche avuto un tempo veramente difficile la prima volta che provo ad ereditare da UIView. Buona fortuna nella tua app! – Icaro

+0

Grazie per la spiegazione completa @Icaro – JayVDiyk