2015-06-12 11 views
8

Próbuję dokonać podklasy UIView w Swift.Przesłanianie init() w aplikacji awarii CustomUIView (EXC_BAD ACCESS)

Howver awarie app (EXC_BAD_ACCESS), gdy inicjator nazywa

Oto klasa

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

Oto jak ja to nazywam

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

Tried aby zamienić self.init() na super.init(), ale to nie będzie co mpile.

Komunikat o błędzie:

Musi zadzwonić do wyznaczonego inicjator superklasy 'UIView'

Convenience inicjator dla 'CustomActionSheet' musi przekazać (z 'self.init') zamiast do łączenia inicjator superklasy (z "super.init")

+1

Czy chcesz umieścić super.init() w miejscu z błędem? – spektr

+0

super.init() nie będzie nawet kompilować @choward. Zaktualizowałem moje pytanie. – JayVDiyk

Odpowiedz

7

Musisz zainicjować swoją UIVIew ramką, nawet jeśli jest zero, musisz również nadpisać init, abyś mógł nitialize zmienne przed wywołaniem kolacji:

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

Wskazówka usunąć inny inicjator wygodę ty create podane wszystkie zmienne są prywatne nie ma potrzeby do tego inicjatora, jednak jeśli chcesz mieć pustą inicjator można po prostu dodać jako:

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

również wielkość ramy mogą być przekazywane lub naprawić wystarczy dokonać odpowiednich zmian i wywołać init(frame: yourFrame)

Reguły dla inicjalizacji z Apple Documentation:

Reguła 1 Wyznaczony inicjator musi wywołać wyznaczonego inicjalizatora z jego bezpośredniej nadklasy.

Reguła 2 Inicjator wygody musi wywołać inny inicjator z tej samej klasy od .

Reguła 3 Inicjator funkcji convenience musi ostatecznie wywoływać inicjator o nazwie .

Prosty sposób, aby pamiętać to:

przeznaczona inicjalizatory zawsze musi przekazać do góry. Convenience Inicjatory muszą zawsze przekazywać dalej.

enter image description here

Mam nadzieję, że pomaga!

+0

Dzięki, działa – JayVDiyk

+1

Cieszę się, że to działa, dodam trochę więcej szczegółów o tym, że miałem naprawdę ciężko pierwszy raz, gdy próbowałem dziedziczyć z UIView. Powodzenia w aplikacji! – Icaro

+0

Dzięki za dokładne wyjaśnienie @Icaro – JayVDiyk

Powiązane problemy