2016-09-09 15 views
14

Mam następujące klasy Hierarchia:Swift 3 ObjC Opcjonalnie Metoda Protokół nie jest wywoływana w Podklasa

class ScrollableViewController: UIViewController, UITableViewDelegate { // ... } 

który implementuje jedną metodę, na przykład protokół UITableViewDelegatetableView:willDisplayCellAt:

W mojej klasie SpecificScrollableViewController, która dziedziczy po ScrollableViewController, nowe opcjonalne metody protokołów nie są już wywoływane, np. tableView(_:heightForRowAt:)

Odpowiedz

29

tl; dr należy poprzedzić deklarację funkcji deklaracją Objective-C, np.

@objc(tableView:heightForRowAtIndexPath:) 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    // return stuff 
} 

zostałem ostrzeżony to jest rozwiązanie, dzięki Swift 3 Migration Guide który stwierdza:

przypadku zastosowania opcjonalnego wymóg protokołu Objective-C w podklasie klasy, która deklaruje zgodność, ci zobaczysz ostrzeżenie "Metoda instancji" ... "prawie spełnia wymagania opcjonalne" ... "protokołu" ... ""

• Obejście: Dodaj atrybut @objc(objectiveC:name:) przed wdrożeniem wymogu opcjonalnego z oryginalnym tekstem Ob selektor jective-C w środku.

Jestem całkiem pewien, że to jest błąd: wydaje się, że dynamika środowiska wykonawczego, który umożliwia sprawdzenie możliwości wyboru nie zostanie właściwie mostkiem w Wielkim Swift Zmiana nazwy gdy metoda protokół jest w podklasie. Przedrostkowanie deklaracji funkcji za pomocą nazwy Objective-C poprawnie mostuje Swift do Objective-C i umożliwia przeszukiwanie metod o nazwach Swift 3 za pomocą canPerformAction:withSender: z poziomu Objective-C

+0

Oh geez to działało dla mnie dzięki! Ugh tak subtelny. – cgossain

+1

@cgossain moja przyjemność! Walczyłem z tym przez 6 godzin, zanim go znalazłem :( –

+0

możesz również użyć prywatnego przed funkcją, aby wyciszyć ostrzeżenie – rashfmnb

2

Wygląda na to, że został naprawiony w Swift 3.0.1 na normalny podklasy, ale nie jest ustalona dla podklasy generycznych:

class A: NSObject, UITableViewDelegate {} 

class B: A { 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {} 
} 

class C<T>: A { 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {} 
} 

print(#selector(B.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAtIndexPath: 
print(#selector(C<Int>.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAt: 

Patrz: https://bugs.swift.org/browse/SR-2817

Aby to naprawić: https://stackoverflow.com/a/39416386/1109892

@objc(tableView:heightForRowAtIndexPath:) 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    // return stuff 
} 
Powiązane problemy