2014-12-18 11 views
6

Próbowałem zacząć i iść od Obj-C do Swift dzisiaj i czytałem dokumentację. Próbowałem stworzyć łatwy IBOlet w Swift i ciągle dawał mi te błędy.IBOutlets i IBactions wymagają! w końcu

View Controller has no initialiser

wymagane init (koder aDecoder: NSCoder) { FatalError ("init (koder :) nie został wdrożony")}

IBOutletproperty has non-optional type 'UILabel'

i że stale wyskakuje z tym kodem:

@IBOutlet var outputLabel : UILabel

, ale kiedy dodaję! znak, że to działa bez błędów jak tak

@IBOutlet var outputLabel : UILabel!

samo dzieje się na IBActions ...

+0

Chciałbym zasugerować tot przeczytać drugą odpowiedź: http://stackoverflow.com/questions/24006975/why-kreślenie- niejawnie-zapakowane -optionals Jest całkiem przydatne. –

+0

@ DánielNagy Mogę zapytać, sprawdziłem kilka samouczków wideo online i nigdy nie wkładają! ... Dlaczego oni i my nie musimy? Dzięki –

+0

Samouczki wideo mogą być nieaktualne - pierwotnie dekorator "IBOutlet" również wprowadził opcję opcjonalną, która została bardzo wcześnie zmieniona. – jrturton

Odpowiedz

7

Przede wszystkim poznać, co jest w rzeczywistości ! i ?

  • Zastosowanie ?: jeżeli wartość może stać nil w przyszłości, tak aby przetestować za to.
  • Użyj !: jeśli naprawdę nie powinno to zejść w przyszłości, ale na początku musi być zerowe.

@IBOutlet:

Kiedy deklarujesz wylot w Swift, kompilator automatycznie konwertuje typ do słaby niejawnie rozpakowany opcjonalnym i przypisuje mu wartość początkową nil.

W efekcie kompilator zastępuje @IBOutlet var name: Wpisz @IBOutlet weak var name: Type! = nil.

Kod Xcode zostanie zmieniony, a Ograniczenie siły zadeklarowane jako @IBOutlet nie będzie zmienną typu opcji, więc po obu rodzajach deklaracji dla @IBOutlet jest Ważna do daty.

@IBOutlet var outputLabel : UILabel! 
@IBOutlet var priceLabel : UILabel? 

Jeśli jednak kontrolować przeciągnij wylot na etykiecie w beta 4 tak się dzieje:

@IBOutlet var priceLabel : UILabel! = nil 
+0

Dzięki! Więc po prostu to powiem. A to obejmuje aspekt samouczka, a następnie ... OK –

5

Zgadza się. W Swift zmienna typu X nie może być zerowa, co oznacza, że ​​musi zostać zainicjalizowana. Oznacza to, że należy zainicjować metodę init lub zainicjować inline.

Ogólnie, widok kontrolery będą deklarować zmienne typów, które są opcjonalne - np

@IBOutlet var outputLabel : UILabel!

Oznacza to, że nie ma potrzeby, aby zainicjować outputLabel i domyślnie jest to wartość nil. Jest to ogólny wzorzec dla zmiennych IBOutlet, ponieważ zmienne są ustawiane poza metodą init.

Jeśli nie wprowadzisz zmiennych opcjonalnych, musisz je zainicjować. Jeśli nie zainicjujesz inline, musisz podać metodę init - stąd błąd, który otrzymujesz.

+0

Jak zapewnić init w szybkim? –

+0

Musisz spojrzeć na kontroler widoku i zastąpić jedną z metod 'init'. Na przykład masz jeden tutaj: wymagany init (koder aDecoder: NSCoder) {super.init (koder: aDecoder)} – tng

+0

Aby zapewnić inicjalizator jest pominięcie punktu, choć. Outlets nie są wypełniane podczas init, są zapełniane, gdy widok jest załadowany, i będą puste do tego momentu. – jrturton

5

Dane konstruktora interfejsów są ładowane po zainicjowaniu kontrolera widoku, więc wyloty nie mogą mieć wartości po inicjalizacji. W przypadku nieopakowanych opcjonalnych właściwości (w tym przypadku gniazd) obiecujesz, że właściwości mogą być zerowe po zainicjowaniu obiektu, ale ich wartość zostanie przypisana później (po załadowaniu pióra lub scenorysu).

1

Ponieważ stos pozwala zadawać pytania w stylu Q i A, umieszczę je również w łatwiejszych słowach. Po prostu umieść ! na facetów z wylotami. Bardzo dziękuję za Twoją pomoc.

0

Błąd

'required' initialized 'init(coder:)' must be provided by subclass of 'UIViewController' 

nagle zaczęło się, gdy dodałem

var start : NSDate 

do poprzednio działającej podklasy UIViewController inaczej wszystko zrobione w IB. Zmiana na

var start : NSDate? 

poprawiona. To jest tak zaskakujący błąd (huh? Init? Coder?) Dla prostej edycji, że ktoś uruchamiający aplikację może zrobić dużo wcześniej, zanim napotkają kodery lub utworzą własne metody init, które być może pomogą wyraźnie pokazać, że potrzeba inicjalizacji nie jest ograniczona do IBOutlets. Powyższe odpowiedzi opisują główną przyczynę.

0

Gdy widoki lub kontrolery widoku są inicjowane z pliku konstruktora interfejsu, ich gniazd nie można jeszcze podłączyć. Będą one połączone tylko po inicjalizacji, więc muszą być opcjonalne. Kiedy jednak inny kod w klasie zostanie wywołany po inicjalizacji, gwarantowane jest, że te gniazda będą połączone. Właśnie dlatego IBOutlets są zawsze deklarowane jako nieopakowane opcje.