Return I'm to Swift

Purpose: To create a common ViewController and TableViewController, which can return from existing storyboards and which will be subclassed by other view controllers and allow them to use this functionality.

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 } } 

The problem is that the compiler forces me to change "I" to this "GenericTableViewController", and if I change it ... it complains that I no longer return "I".

Is there anything that can be fixed?

+6
source share
2 answers

The following actions must be performed:

 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 } 

Basically, you create a generic version of your existingStoryboardControllerTemplate and add an extra method to help the compiler infer the type T

+17
source

Based on Thomas Kamin's answer, here is an extension of the UIViewController in Swift 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 } } 

If your storyboard controller identifiers match their class names, just call the from(storyboard:) class function with the name.

 let viewController = MyCustomViewController.fromStoryboard("Main") 

Otherwise, specify the identifier.

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

If you already have an instance of the storyboard, use can use it.

 let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) let viewController = MyCustomViewController.fromStoryboard(storyboard, withIdentifier: "ID") 
+2
source

Source: https://habr.com/ru/post/989052/


All Articles