我遇到了这个问题,我无法解决这个问题,但却找不到相关问题。
我的情况是,从工厂函数我想要返回一个UIViewController
实例,它也实现了一个协议,我们称之为Protocol
。我想知道是否有人经历过这个并找到了解决办法吗?
在Objective-C中它看起来像这样:
- (UIViewController<Protocol>*)createControllerForIdentifier:(NSString*)identifier
有没有Swift方式来写这个?
将Protocol
限制为具体的类或子类对于我的情况是可以的。
我发现this thread但无法转换为我的案例
感谢您的帮助。
答案 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