私はいくつかの繰り返しのUIViewControllerボイラープレートは、私がカプセル化したかったので、私は、この一般的なのUIViewControllerの拡張メソッドを定義していることを周囲に飛散していた:なぜこのSwift汎用関数を使用して型を強制する必要がありますか?
extension UIViewController {
func instantiateChildViewController<T: UIViewController>(
storyboardName: String? = nil,
identifier: String? = nil
) -> T {
let storyboard: UIStoryboard!
if let name = storyboardName {
storyboard = UIStoryboard(name: name, bundle: nil)
}
else {
storyboard = UIStoryboard(name: "\(T.self)", bundle: nil)
}
let vc: T!
if let identifier = identifier {
vc = storyboard.instantiateViewController(withIdentifier: identifier) as! T
}
else {
vc = storyboard.instantiateInitialViewController()! as! T
}
self.addChildViewController(vc)
self.view.addSubview(vc.view)
return vc
}
}
しかし、私はそうのようにこの拡張機能を使用する場合:
class ChildViewController: UIViewController { /*...*/ }
class ParentViewController: UIViewController {
private var childVC: ChildViewController!
//...
func setupSomeStuff() {
self.childVC = self.instantiateChildViewController() //<-- Compiler error
let vc: ChildViewController = self.instantiateChildViewController() //<-- Compiles!
self.childVC = vc
}
}
コンパイラエラーCannot assign value of UIViewController to type ChildViewController!
が上記のコメントの行に表示されます。しかし、私が明示的に型を与える中間変数を使用すると、それは機能します。
これはスウィフトバグですか? (Xcode 8.1)ジェネリックスがどのように機能するかについての私の解釈は、この場合、T
はより具体的にはChildViewController
と同じでなければならず、あまり制約のないものでなければなりません。UIViewController
。
self.childVC = self.instantiateChildViewController() as ChildViewController
うん以外のどこにそれを設定しようとしている場合も、あなたのchildVCは '、VARはなくLETする必要がありますchildVC'は私のコードではvarですが、私はコードを適切な例に縮小すると、誤ってletに変更されました。質問を編集します。 – Ryan