2016-05-17 61 views
0

我有這樣的視圖控制器,意味着一種通用的方式來呈現的模型對象細節的UIViewController:鏈接故事板與通用

class APIModelDetailsVC<T where T: APIModel>: UIViewController {...} 

我想我的故事板使用這個類。我能夠把它分配在Interface Builder:

enter image description here

我做這個視圖控制器的一個tableview中的didSelect法制備(包括指定類型的通用佔位符):

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    print("didSelectRowAtIndexPath \(indexPath.row)") 
    if let vc = UIStoryboard(name: "APIModelDetailsVC", bundle: nil).instantiateInitialViewController() as? APIModelDetailsVC<StarWarsPerson> { 
    vc.model = data[indexPath.row] 
    self.navigationController?.pushViewController(vc, animated: true) 
    } 
} 

當我嘗試導航到此視圖控制器時,出現以下控制檯錯誤:

Unknown class _TtC14api_collection17APIModelDetailsVC in Interface Builder file. 

是否有記錄的限制與故事板?有沒有一種方法可以/應該指定通用,故事板可以鏈接到它?

回答

3

故事板有一個泛型類的問題。問題是Interface Builder通過Objective-C運行時與ViewController通信。因此,InterfaceBuilder僅限於Objective-C提供的功能。在這種情況下,不支持泛型。

解決方法是使用NSObject的​​方法。

例如,如果您有提到的ViewController類:

class APIModelDetailsVC<T where T: APIModel>: UIViewController {...} 

您應該創建一個 「虛擬」 的ViewController如:

class StartWasModelDetailsVC: APIModelDetailsVC<StarWarsPerson> {...} 

,並在故事板設置這最後的ViewController。之後,爲了在Objective-c運行時中完成這項工作,您應該在AppDelegate中或在加載此控制器之前的某個位置添加以下內容。

StartWasModelDetailsVC.load() 

希望它有幫助!

+0

而一年後。你釘了它。 :) 謝謝! – SimplGy

2

我只是碰到了同樣的問題,與其他的解決方法提出了:

我只在代碼中創建我的通用的UIViewController。在IB中,然後在XIB文件中創建一個UIView,該文件包含我需要的所有控件以及一個名爲「mainView」的類,該類具有所有插座。

在通用的UIViewController viewDidLoad中()我然後從XIB加載視圖,導線它並且將其插入到視圖控制器的這樣的主視圖:

class RSListViewController<T: RSObjectProtocol>: UIViewController, UITableViewDelegate { 

override func viewDidLoad() { 

    super.viewDidLoad() 

    guard let mainView = Bundle.main.loadNibNamed("mainView", owner: self, options: nil)?.first as? MainView else { return } 

    self.mainView = mainView 
    self.mainView.tableView.delegate = self 
    self.mainView.segControl.addTarget(self, action: #selector(RSListViewController.listTypeChanged(_:)), for: .valueChanged) 

    self.view.addSubview(mainView) 

} 

唯一要注意,我可以看到到目前爲止,你不能處理網點一樣,直接

self.buttonAdd 

,但需要經過的觀點類似

self.mainView.buttonAdd 

除了上述代碼示例中的代碼外,我使用addTarget通過代碼連接事件。

這是一種混合,如果你不想做「代碼只」,但在我看來,它似乎工作正常。它確實阻止了許多虛擬ViewController的創建,這在我看來有點違背泛型的想法。但這只是個人品味的問題,並不意味着以任何方式批評Federico Ojeda的解決方案。