简体   繁体   English

快速向下转换和协议变量

[英]Swift downcasting and protocol variables

I have a swift protocol that contains one property: 我有一个包含一个属性的swift协议:

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. 在我的Wireframe类中,变量实际上是MenuViewController类型,但必须声明为UIViewController以确认协议。 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. 我必须使用(self.rootViewController as!MenuViewController)将它向下转换为我想要的正确类,以便能够访问其属性。 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! 非常感谢!

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 然后在你的采用类中将rootViewController类型设置为MenuViewController

class MenuWireframe : WireframeProtocol{

let rootViewController: MenuViewController

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

If you can change protocol declaration, use @zelb's answer. 如果您可以更改协议声明,请使用@ zelb的答案。 If you cannot, you could do something like: 如果你不能,你可以这样做:

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

    let menuViewController: MenuViewController!

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

Did you try this one : 你试过这个吗:

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

class MenuWireframe : WireframeProtocol
{
    let rootViewController: WireframeProtocol

    init()
    {
        //...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM