Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift downcasting and protocol variables

Tags:

ios

swift

iphone

I have a swift protocol that contains one property:

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

I then have a class that implements this protocol as such:

class MenuWireframe : WireframeProtocol
{
    let rootViewController: UIViewController

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

In my Wireframe class the variable is actually of type MenuViewController but has to instead be declared as UIViewController to confirm to the protocol. I have to use (self.rootViewController as! MenuViewController) to downcast it to the correct class I want so as to be able to access its properties. It is fine in my simple example above but is not very readable, especially in more complex situations. Is there a better way to declare the protocol variable?

Many thanks!

like image 927
bennythemink Avatar asked May 19 '15 11:05

bennythemink


3 Answers

Yes there is a better way and thats by using generic protocols. To implement that you must declare your protocol similar like this :

protocol WireframeProtocol{

    typealias RootViewController : UIViewController
    var rootViewController: RootViewController  { get }

}

then in your adoption class set rootViewController type as MenuViewController

class MenuWireframe : WireframeProtocol{

let rootViewController: MenuViewController

    init(){
        self.rootViewController = MenuViewController(nibName: "MenuViewController", bundle: nil)
        self.rootViewController.presenter = MenuPresenter(interactor: MenuInteractor())
    }
}
like image 119
Zell B. Avatar answered Oct 13 '22 13:10

Zell B.


If you can change protocol declaration, use @zelb's answer. If you cannot, you could do something like:

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

    let menuViewController: MenuViewController!

    init()
    {
        menuViewController = MenuViewController(...)
        //...
    }
}
like image 38
Jakub Vano Avatar answered Oct 13 '22 12:10

Jakub Vano


Did you try this one :

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

class MenuWireframe : WireframeProtocol
{
    let rootViewController: WireframeProtocol

    init()
    {
        //...
    }
}
like image 25
Vincent Saluzzo Avatar answered Oct 13 '22 12:10

Vincent Saluzzo