返回实现协议的具体类的对象

时间:2016-02-04 16:35:42

标签: ios swift

我遇到了这个问题,我无法解决这个问题,但却找不到相关问题。

我的情况是,从工厂函数我想要返回一个UIViewController实例,它也实现了一个协议,我们称之为Protocol。我想知道是否有人经历过这个并找到了解决办法吗?

在Objective-C中它看起来像这样:

- (UIViewController<Protocol>*)createControllerForIdentifier:(NSString*)identifier

有没有Swift方式来写这个?

Protocol限制为具体的类或子类对于我的情况是可以的。

我发现this thread但无法转换为我的案例

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

根据具体情况,有几种选择。这是一种可以提供帮助的一般方法。但是,我建议重写代码,这不是一个真正的问题。 Swift和Objective-C是不同的语言,并且一些设计模式根本不是(也可能永远不会)两种语言都可用。在这种情况下,移植代码需要从头开始重新思考代码。

通过引入如下的绑定协议,您可以实现安全性和便利性:

// protocol you want to implement
// this may possibly be implemented by other types besides our Base (no restrictions)
protocol P1 {
    func run()
}


// base class of objects to instantiate
class Base {
    // Base specific method
    func display() {
        print("Displaying...")
    }
}


// wrapper to get both P1 and Base
// our special protocol will be dedicated to P1 and Base
protocol PB : P1 {      // already a P1
    // property to safely get this instance as a Base without casting
    var asBase : Base { get }
}


// extension to safely implement the binding for P1 and Base
// anything we implement in this extension is safe for both P1 and Base
extension PB where Self : Base {
    var asBase : Base { return self }
}


// concrete subclass of Base which also implements PB and hence P1
class X : Base, PB {
    // implement protocol
    func run() {
        print("Running...")
    }
}


// factory function to make a concrete instance of Base implementing P1
func makePB() -> PB {
    return X()
}


let pb = makePB()
pb.run()                // directly access as P1
pb.asBase.display()     // both safe and easy to access as Base

答案 1 :(得分:1)

Swift4❤️

func createController(for identifier: String) -> (UIViewController & Protocol)

答案 2 :(得分:0)

一种方法如下:

protocol Protocol {
    func bar()
}

class MyViewController : UIViewController, Protocol {

    func bar() {
        print("Bar")
    }

    static func getInstance() -> MyViewController {
        return self.init()
    }

}

/* Example usage */
let foo = MyViewController.getInstance() 
print(foo.dynamicType) // MyViewController
foo.bar() // Bar

/* Naturally works to pass foo to 'Protocol' type constrained function */
func foobar<T: Protocol>(fizz: T) {
    fizz.bar()
}
foobar(foo) // bar

或者,对于更通用/可重用的方法(具有简单init()初始化程序的类/结构的工厂方法):

/* Setup generic factory */
protocol FactoryInitializers {
    init()
}

protocol FactoryMethods {
    typealias T: FactoryInitializers
}
extension FactoryMethods {
    static func getInstance() -> T {
        return T()
    }
}

protocol Factory : FactoryMethods, FactoryInitializers { }

/* Apply for your example, with conformance to 'Factory' (to get access 
   to default implementation 'getInstance' method) as well as a custom 
   protocol 'Protocol'              */
protocol Protocol {
    func bar()
}

class MyViewController : UIViewController, Factory, Protocol {
    typealias T = MyViewController

    func bar() {
        print("Bar")
    }
}

与上述更简单的版本具有相同的结果:

let foo = MyViewController.getInstance() // OK, MyViewController conforms to Factory
print(foo.dynamicType) // MyViewController
foo.bar() // Bar

/* Naturally works to pass foo to 'Protocol' type constrained function */
func foobar<T: Protocol>(fizz: T) {
    fizz.bar()
}
foobar(foo) // bar