2016-11-18 14 views
2

В настоящее время для загрузки ViewController с таким же nibname я использую код следующимнагрузки ViewController с СИБ использованием дженериков

let recommendationVC : RecommendationVC = RecommendationVC(nibName: "RecommendationVC", bundle: nil) 

Я чувствую, указав nibname является unncessary как это совпадает с именем контроллера. Поэтому я решил использовать дженерики и вывести тип и имя острия с помощью дженериков

protocol NibIdentifiable { 
    static var nibNameIdentifier: String { get } 
} 

// MARK: - Indentifies each storyboard from its classname. 
extension NibIdentifiable where Self: UIViewController { 
    static var nibNameIdentifier: String { 
     return String(describing: self) 
    } 
} 
extension UIViewController :NibIdentifiable 
{ 

} 

extension UIViewController { 
    func instantiate<Controller: UIViewController>(_: Controller.Type) -> Controller where Controller: NibIdentifiable { 

     guard let controller = Self(nibName:Controller.nibNameIdentifier,bundle:nil) as? Controller else { 
      fatalError("Could not dequeue cell with identifier: \(Controller.nibNameIdentifier)") 
     } 

     return controller 
    } 
} 

Но при попытке создать экземпляр VC,

let recommendationVC :RecommendationVC = UIViewController.instantiate() 

получения ошибки Общий параметр «Controller» не может быть выведено

Что не так в этом подходе?

+0

пусть recommendationVC: RecommendationVC = RecommendationVC.instantiate () попробуйте вот так –

+0

@KonstantinKryzha новский я это пробовал. Облицовка одной и той же проблемы –

+1

Когда имя низа совпадает с именем класса, вам даже не нужно указывать его. Просто сделайте 'let рекомендацияVC = РекомендацияVC()' должна работать нормально. – dan

ответ

1
class Rec : UIViewController { 
    let r : String = "1231231" 
} 

protocol NibIdentifiable { 
    static var nibNameIdentifier: String { get } 
} 

// MARK: - Indentifies each storyboard from its classname. 
extension NibIdentifiable where Self: UIViewController { 
    static var nibNameIdentifier: String { 
     return String(describing: self) 
    } 

    static func instantiate() -> Self { 

     guard let controller = Self(nibName:Self.nibNameIdentifier,bundle:nil) as? Self else { 
      fatalError("Could not dequeue cell with identifier: \(Self.nibNameIdentifier)") 
     } 

     return controller 
    } 

} 

extension UIViewController : NibIdentifiable { 
} 

let x : Rec = Rec.instantiate() 

Это должно работать.

В моем случае я использую протокол Storyboardable. и инициировать контроллер из конкретной раскадровки.

3

Добавьте расширение для UIViewController

extension UIViewController { 
    static func instantiateFromNib() -> Self { 
     func instantiateFromNib<T: UIViewController>(_ viewType: T.Type) -> T { 
      return T.init(nibName: String(describing: T.self), bundle: nil) 
     } 

     return instantiateFromNib(self) 
    } 
} 

, а затем использовать так же, как что

пусть myViewController = MyViewController.instantiateFromNib()

+1

Спасибо! это сработало для меня, хотя я не занимался внутренней функцией; Я просто прямо называю 'return self.init (nibName: String (описание: self), bundle: nil);' – hasen