在使用泛型函數時,通用參數的類型可以根據您分配結果的變量的類型(或者在返回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版本中可能會得到改進,但目前是不可能的。 –