2016-12-08 8 views
0

私はいくつかの繰り返しの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

答えて

1
:私は、私は私が見つけた唯一の回避策は明らかに拡張子があまり説得力になり、ローカル変数、である、などの明示的なキャストを行うには、 private var childVC: ChildViewController?として childVCを定義した場合、同じ問題を取得します

私もこれを見ました。コンパイラが期待どおりに処理していないOptionalsの周りには、奇妙な動作があると思います。

関数の戻り値を任意の値に変更すると、問題なく動作するはずです。

func instantiateChildViewController<T: UIViewController>(//whateverParams) -> T!

または

func instantiateChildViewController<T: UIViewController>(//whateverParams) -> T?

あなたは初期化子

+0

うん以外のどこにそれを設定しようとしている場合も、あなたのchildVCは '、VARはなくLETする必要がありますchildVC'は私のコードではvarですが、私はコードを適切な例に縮小すると、誤ってletに変更されました。質問を編集します。 – Ryan

関連する問題