2014-06-29 8 views
8

Problem z podklasą UITextView (i UICollectionView) jest taki, że wyznaczonym konstruktorem jest "initWithFrame". Ale w rzeczywistości, gdy ładuje się z storyboardu, zostanie wywołany initWithCoder.Swift: Podklasowanie UITextView lub UICollectionView i właściwe inicjowanie

class BorderedTextView: UITextView { 
    //will be called 
    init(coder: NSCoder?){ 
     //constant values here is not an option 
     super.init(frame: CGRectMake(0,0,100,100), textContainer: nil) 
    } 
    //will not be called 
    init(frame: CGRect, textContainer: NSTextContainer!) { 
     super.init(frame: frame, textContainer: textContainer) 
    } 
} 

W rezultacie nie mogę nazwać żadnego interfejsu dostosowywania kodu na startowych i zapewniają żadnej wartości inicjalizacji zmiennych Swift oprócz domyślnych.

Przypuszczam, że problem można tymczasowo rozwiązać, wyodrębniając rozmiar ramki z "kodera", ale nie znalazłem klucza.

Jakieś pomysły lepsze od wartości ramek kodu?

+0

Spodziewam się, że 'super.init (koder: koder)' działa - i dla podklas UIView lub UILabel to robi (przynajmniej kompilator nie narzeka). Ale dla podklas 'UITextView' nie powiedzie się z komunikatem o błędzie" Musi wywołać oznaczony inicjator ... ". Błąd Swift? –

+0

Możliwe obejście może polegać na inicjalizacji w 'awakeFromNib'. –

+0

Masz rację, wygląda na to, że działa dla UIView (zaktualizowałem pytanie). Ale mam również ten sam problem z UICollectionView, więc problem nie dotyczy tylko UITextView. –

Odpowiedz

12

(Z powyższych komentarzy :) To wygląda jak błąd Swift. initWithCoder: nazywa kiedy widokiem (lub kontroler widoku) jest tworzony z pliku Storyboard lub NIB i nadrzędnym że metoda działa w Objective-C:

- (instancetype)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    if (self) { 
     // Initialization code 
    } 
    return self; 
} 

ale równoważny kod Swift

class BorderedTextView: UITextView { 
    init(coder: NSCoder!) { 
     super.init(coder: coder) 
    } 
} 

kończy się niepowodzeniem z komunikatem o błędzie "musi wywołać określony inicjator nadklasy" UITextView "".

Problem ten występuje przy wszystkich podklas UIView które mają własną wyznaczony inicjatora (np UITextView, UICollectionView). Z drugiej strony problem nie występuje w przypadku podklas o numerze UILabel, który nie ma wyznaczonego inicjalizatora. Język Swift bardzo ściśle określa wywołanie inicjatora superklasy, , ale powinien istnieć sposób nadpisania initWithCoder: dla wszystkich podklas niestandardowych UIView, więc uważam to za błąd Swift.

Jako obejście, można zrobić niestandardową inicjalizacji w

override func awakeFromNib() { 
    super.awakeFromNib() 
    // ... 
} 

Aktualizacja dla Swift 1.2: To najwyraźniej został naprawiony. Zmieniono parametr , nie jest to już nieopakowany plik opcjonalny. Więc to kompiluje i działa zgodnie z oczekiwaniami (testowane z Xcode 6.4):

class BorderedTextView: UITextView { 
    required init(coder: NSCoder) { 
     super.init(coder: coder) 

     // ... 
    } 
} 

Aktualizacja Swift 2 (Xcode 7):init(coder:) jest failable initializer teraz:

class BorderedTextView: UITextView { 
    required init?(coder: NSCoder) { 
     super.init(coder: coder) 

     // ... 
    } 
} 
+0

Czy to działa w Swift 1.2? – Jacob

0

Bardziej kompletna odpowiedź dla Swift 3:

class ValidatedTextField:UITextField, UITextFieldDelegate 
{ 
    required override init(frame: CGRect) 
    { 
     super.init(frame: frame) 
     //custom code 
     self.delegate = self 
    } 

    required init?(coder: NSCoder) 
    { 
     super.init(coder: coder) 
     //custom code 
     self.delegate = self 
    }