2015-05-19 13 views
6

mam szybki protokół, który zawiera jedną właściwość:Swift rzutowanie w dół i protokołów zmienne

protocol WireframeProtocol: class 
{ 
    var rootViewController: UIViewController { get } 
} 

Mam następnie klasy, która implementuje ten protokół jako takie:

class MenuWireframe : WireframeProtocol 
{ 
    let rootViewController: UIViewController 

    init() 
    { 
     self.rootViewController = MenuViewController(nibName: "MenuViewController", bundle: nil) 
     (self.rootViewController as! MenuViewController).presenter = MenuPresenter(interactor: MenuInteractor()) 
    } 
} 

W mojej klasie Szkielet zmienna jest faktycznie typu MenuViewController, ale musi zostać zadeklarowany jako UIViewController w celu potwierdzenia protokołu. Muszę użyć (self.rootViewController jako! MenuViewController), aby obniżyć go do odpowiedniej klasy, chcę, aby móc uzyskać dostęp do jego właściwości. W moim prostym przykładzie powyżej wszystko jest w porządku, ale nie jest czytelne, szczególnie w bardziej złożonych sytuacjach. Czy istnieje lepszy sposób deklarowania zmiennej protokołu?

Wielkie dzięki!

+1

Ponieważ używasz Viper, można/należy zadeklarować swój rootviewcontroller jako protokół (protokół View) i określić słabe własności tam, który będzie prezenter . –

+0

Cześć Daniel, to prawda, ale ta sprawa ma inny cel. Chciałbym mieć protokół, w którym każdy szkielet jest zgodny z tym, który udostępnia kontroler UIViewController, którego mogę używać do celów nawigacyjnych. Przypuszczam, że mogę nadal używać tego protokołu widoku, jeśli protokół dotyczy tylko UIViewControllers ... mmm Sprawdzę to i skontaktuję się z Tobą – bennythemink

+0

@bennythemink czy sprawdziłeś moją odpowiedź? –

Odpowiedz

3

Tak istnieje lepszy sposób i przy użyciu protokołów ów rodzajowe. Aby wdrożyć że trzeba zadeklarować swoją protokół podobnie jak to:

protocol WireframeProtocol{ 

    typealias RootViewController : UIViewController 
    var rootViewController: RootViewController { get } 

} 

potem w swojej klasie przyjęcie ustaw typ rootViewController jak MenuViewController

class MenuWireframe : WireframeProtocol{ 

let rootViewController: MenuViewController 

    init(){ 
     self.rootViewController = MenuViewController(nibName: "MenuViewController", bundle: nil) 
     self.rootViewController.presenter = MenuPresenter(interactor: MenuInteractor()) 
    } 
} 
+0

Hi zellb, to działa!Ale nie jestem do końca pewien, dlaczego tak się dzieje. Czy możesz mi to wyjaśnić? – bennythemink

+1

Typ aliasy definiują alternatywną nazwę dla istniejącego typu, więc w tym przypadku zadeklarowałem nową nazwę dla wszystkich typów dziedziczonych z UIViewController (w wierszu 'typealias RootViewController: UIViewController'). Po tym ustawiam typ rootViewController na nowo napisany tak, aby var rootViewController mógł pomieścić dowolną wartość utworzoną z klas dziedziczonych z UIViewController, więc teraz możesz ustawić ją bezpośrednio jako MenuViewController bez żadnych wymagań dotyczących odlewania. Mam nadzieję, że było jasne –

+0

Idealne, dziękuję Zellb. Teraz ma to dla mnie sens :) – bennythemink

1

Czy spróbować tego:

protocol WireframeProtocol: UIViewController { 
    var rootViewController: UIViewController { get } 
} 

class MenuWireframe : WireframeProtocol 
{ 
    let rootViewController: WireframeProtocol 

    init() 
    { 
     //... 
    } 
} 
+0

Cześć, dostaję "nieklasowany typ WireframeProtocol nie może odziedziczyć po klasie UIViewController":/Nie zadziała tak, obawiam się. Dzięki za twoją sugestię – bennythemink

+0

tak, wskazałem tę brakującą na początku Swift w projekcie. W Objective-C moglibyśmy stworzyć coś takiego jak 'UIViewController * rootViewController;' ... –

2

Jeśli można zmienić deklarację protokołu, odpowiedź Przymież @ zelb użytkownika. Jeśli nie, można zrobić coś takiego:

class MenuWireframe : WireframeProtocol 
{ 
    var rootViewController: UIViewController { 
     return menuViewController 
    } 

    let menuViewController: MenuViewController! 

    init() 
    { 
     menuViewController = MenuViewController(...) 
     //... 
    } 
} 
+0

Cześć, dziękuję za twoją sugestię. Właśnie to przetestowałem i to nie działa, obawiam się. Po pierwsze nie mogę użyć "let" z tym podejściem, a po drugie wciąż muszę rzucić rootViewController, aby wpisać MenuViewController, jeśli chcę uzyskać dostęp do jego właściwości :(ale dzięki za twoją sugestię – bennythemink

+0

@bennythemink Dlaczego nie możesz użyć 'let'? pomysł jest uzyskanie dostępu do 'menuViewController' zamiast' rootViewController' gdzie wiesz, że dany obiekt jest w rzeczywistości 'MenuWireFrame' nie jest arbitralny' WireFrameProtocol' –

+0

Witam, nie mogę użyć "let" jako rootViewController jest teraz obliczona właściwość w Twojej sugestii. może być pedantyczny, ale teraz oznacza to również, że mam dwie właściwości zamiast jednej w klasie, ale jeszcze raz dziękuję za cynk: – bennythemink

Powiązane problemy