2015-06-13 18 views
6

目的:製作一個通用的ViewController和TableViewController,它們可以從現有的故事板中返回自己,並且可以由其他視圖控制器進行子類化,並允許它們使用此功能。Swift中的自我複製

class GenericTableViewController: UITableViewController 
{ 
    //MARK: Storyboard 
    class func storyboardName() -> String 
    { 
     return "" 
    } 

    class func storyboardIdentifier() -> String 
    { 
     return "" 
    } 

    class func existingStoryboardControllerTemplate() -> Self 
    { 
     return UIStoryboard.storyboardWithName(storyboardName()).instantiateViewControllerWithIdentifier(storyboardIdentifier()) as! Self 
    } 
} 

的問題是..編譯器迫使我自我改變這種「GenericTableViewController」如果我改變它...它抱怨,我再也不能回到「自我」。

有什麼可以解決這個問題嗎?

+0

在一個類型方法中Self指的是類型,但是你返回一個實例並試圖將它轉換爲一個類型。 – Andrea

+0

看看http://stackoverflow.com/questions/25645090/protocol-func-returning-self# – ABakerSmith

+0

我看了,但對我來說有點困惑.. - >我無法理解如何適應它的方式。 – Fawkes

回答

16

做以下應該工作:

class func existingStoryboardControllerTemplate() -> Self { 
    return existingStoryboardControllerTemplate(self) 
} 

private class func existingStoryboardControllerTemplate<T>(type: T.Type) -> T { 
    return UIStoryboard(name: storyboardName(), bundle: nil).instantiateViewControllerWithIdentifier(storyboardIdentifier()) as! T 
} 

基本上你創建你existingStoryboardControllerTemplate的通用版本,並添加一個額外的方法來幫助編譯器推斷T類型。

+0

作品)謝謝) – Fawkes

+0

如何專注於這樣的第二種方法? existingStoryboardControllerTemplate (類型:T.Type) – Laurent

+1

@JohnDifool肯定會工作。然而,在這種情況下,這樣做不會有什麼特別的優勢,因爲第二種方法基本上是一個私有方法(回答編輯),它只能從GenericTableViewController類(或子類)調用, –

1

從托馬斯·卡明答案大廈,這裏有一個UIViewController擴展斯威夫特3.

extension UIViewController { 

    class func fromStoryboard(_ name: String, in bundle: Bundle? = nil, withIdentifier id: String? = nil) -> Self? { 
    return fromStoryboard(UIStoryboard(name: name, bundle: bundle), withIdentifier: id) 
    } 

    class func fromStoryboard(_ storyboard: UIStoryboard, withIdentifier id: String? = nil) -> Self? { 
    return fromStoryboard(storyboard, withIdentifier: id, as: self) 
    } 

    private class func fromStoryboard<T>(_ storyboard: UIStoryboard, withIdentifier id: String? = nil, as type: T.Type) -> T? { 
    return storyboard.instantiateViewController(withIdentifier: id ?? "\(type)") as? T 
    } 

} 

如果你的故事板視圖控制器標識符匹配他們的類名,只要調用類函數from(storyboard:)使用一個名稱。

let viewController = MyCustomViewController.fromStoryboard("Main") 

否則,提供一個標識符。

let viewController = MyCustomViewController.fromStoryboard("Main", withIdentifier: "ID") 

如果您已經有故事板的實例,可以使用它。

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) 

let viewController = MyCustomViewController.fromStoryboard(storyboard, withIdentifier: "ID")