在使用泛型函数时,通用参数的类型可以根据您分配结果的变量的类型(或者在返回Void
的函数的情况下,根据您传递给参数的参数的具体类型类型T
)。
在你的例子中,你不告诉编译器你的vc
变量是什么类型,所以你会得到一个错误。你可以像这样很容易解决这个问题:
class MyViewController: UIViewController, Routable {
public static func provideInstance(id: String?) -> Self? {
return self.init()
}
}
// give `vc` a concrete type so `T` can be inferred:
let vc: MyViewController? = Router().getDestinationViewController(url: URL(string: "www.domain.com/users/1")!)
编辑:
由于您的问题似乎是一起的“我怎么复制的UIViewController *<Routable>
Objective-C的概念”线以上,这你不能在Swift中做,我会提到你可能会觉得值得回顾一下你的设计。当我从Objective-C移动到Swift时,我认为无法使用类似UIViewController *<Routable>
这样的东西很难解决(甚至向Apple提交了一个关于它的错误报告),但实际上它并不是一个问题。
您的Router
类需要一些信息在您的视图控制器能够正确路由。在你的例子中,你正在寻找一个与特定URL关联的视图控制器。言下之意是,你UIViewController
有财产包含此URL,因此而不是返回一个Routable
协议,正确的做法是子类的UIViewController像这样:
class RoutableViewController: UIViewController {
let url: URL = URL(string: "...")
}
现在你的路由器看起来像:
class Router {
var routables = [RoutableViewController]()
func viewControllerWithURL(_ url: URL) -> RoutableViewController? {
return routables.first
}
}
现在你不需要做任何类型转换,并且(明显)保持类型安全。
编辑2:
这里有一个解决方案,使每鉴于控制器符合Routable
(我不认为你获得多少与我在以前的编辑提出的解决方案,但在这里它是无论如何) :
protocol Routable {
var url: URL? { get }
}
// now every UIViewController conforms to Routable
extension UIViewController: Routable {
var url: URL? { return nil }
}
class MyViewController: UIViewController {
private let myURL: URL
override var url: URL? { return myURL }
init(url: URL) {
myURL = url
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class Router {
var viewControllers: [UIViewController] = [
MyViewController(url: URL(string: "foo")!),
UIViewController()
]
func viewController(for url: URL) -> UIViewController? {
for viewController in viewControllers {
if viewController.url == url { return viewController }
}
return nil
}
}
来源
2016-11-30 17:40:40
par
是否真的不可能返回也是可路由的UIViewController?这在objc中是可能的 - (UIViewController *)gimeeSomething' –
aryaxt
在Swift中无法表达这一点。你将不得不在UIViewController中添加你想要的特定方法到Routable协议上。这是一个众所周知的限制,在未来的Swift版本中可能会得到改进,但目前是不可能的。 –