2016-03-31 34 views
5

我最近從UITableViewController中簡單繼承了我的類BookTableViewController,因此它現在繼承自其自身繼承的泛型類FetchedResultsTableViewController<TResultType, TCellType>UITableViewController使用繼承自故事板中的泛型類的類時,「接口構建器文件中的未知類」

類的聲明是這樣的:

class BookTableViewController: FetchedResultsTableViewController<Book, BookTableViewCell> { 

    override func viewDidLoad() { 
     // breakpoints in here do not catch! 
    } 

} 

class FetchedResultsTableViewController<TResultType, TCellType: UITableViewCell>: 
    UITableViewController, NSFetchedResultsControllerDelegate { 

    // implementation here 

} 

在故事板,自定義類和模塊都設置了,我可以單擊箭頭跳轉到代碼爲BookTableViewController類,提示故事板與班級正確鏈接。然而,當我嘗試運行應用程序時,類不能被識別 - 在viewDidLoad()代碼不能運行,運行我的應用程序時,我收到以下記錄消息:在Interface Builder文件

未知類_TtC12Reading_List23BookTableViewController。

我正在運行XCode 7.3(Swift 2.2)。這是故事板的一個限制,一個錯誤,還是我錯過了什麼?

謝謝!

UPDATE

一些實驗後,它似乎是相關的通用繼承,而不是類的可訪問性。隨着定義以下類:

import Foundation 
import UIKit 

// Both of these classes are accessible by the Storyboard 
class FirstInheritance : UITableViewController{} 
class SecondInheritance : FirstInheritance{} 

// The generic class is also accessible 
class GenericViewController<T> : UITableViewController{} 

// But this class is not accessible... 
class ConcreteViewController : GenericViewController<String>{} 

除了ConcreteViewController所有類都建議在故事板的類自動完成(儘管通用類也不起作用,因爲沒有辦法來指定在故事板的類型參數)。

+0

故事板不知道FetchedResultsTableViewController嗎? –

+0

根據您的評論,我注意到Storyboard中的Class字段_does_自動完成了'FetchedResultsTableViewController',但_does not_ autocomplete to'BookTableViewController'。 (當然,'FetchedResultsTableViewController'不起作用,因爲我們不能指定類型參數)。 我在問題的更新中創建了一個更簡單的行爲示例。另請參閱示例[這裏](https://github.com/AndrewBennet/GenericTableView)。我開始認爲這是故事板的限制... –

+0

啊,是的,這是一個限制。基本上同樣的問題在這裏被問到:http://stackoverflow.com/a/32899800。我可能會嘗試使用帶有typealiases和擴展名的協議來代替默認行爲。 –

回答

4

遊戲遲到了,但這個信息可能會適用於任何人碰到線程。實際上,據我所知,現在,就像Swift 3一樣,在故事板中,對於泛型的一些尷尬的支持。我已經設法編寫一個擴展UIViewController的泛型基類,然後約束該泛型類的幾個子類並在故事板中使用它們。

的實際代碼也有類似的佈局是什麼波紋管規定:

class GenericParent: UIViewController { 
    // Has a few, non-generic members ... 
} 

class ActualGenericClass<T>: GenericParent { 
    // There are more generic members in the actual class 
    var adapter: Adapter<T> = Adapter() 
} 

// This class is usable in Interface Builder; 
// although auto-complete won't show it, fully writing down 
// the class name works 
class SpecificInstanceOfActualGenericClass: ActualGenericClass<Int> { 
    @IBOutlet weak var tableView: UITableView! 
} 

完美的作品,讓我吃驚!

在另一方面,下面的例子似乎不工作:

class GenericCell<T>: UITableViewCell { 
    var node: T? = nil 
} 
class SpecificCell: GenericCell<Int> { 
    @IBOutlet weak var coolTitleLabel: UILabel! 
} 

像以前一樣,明確地寫在Interface Builder中細胞的類名(對細胞的動態原型)設置的類表格視圖單元格和插座都可見。

但是,在運行時,當實例化包含單元的動態原型的UIViewController時,會顯示「接口構建器文件中的未知類」警告,並且應用程序在出現單元時出現故障。

所以@Andew班納特,該語句:

故事板不支持從通用類

繼承的類

似乎是不正確的100%更多,雖然你在最少的權利;這是我第一次設法把這個關掉,儘管只是部分!

它讓我感到有些事情有效,有些則不行,但總比沒有好。

這是在Java非常直截了當...

2

故事板不支持直接或間接從泛型類繼承的類。如果您使用從故事板中的泛型類繼承的類,那麼在運行時會出現錯誤,指出該類未知。

另一種方法是使用一個協議與類型別名和擴展:

protocol MyProtocol { 
    associatedtype genericType1 
    associatedtype genericType2 

    func myFunc(argument1: genericType1, argument2: genericType2) 
} 

extension MyProtocol { 
    func defaultFunc(argument1: genericType1){ 
     // default implementation here 
    } 
} 

該協議被使用如下:

class NonGenericClass: MyProtocol { 
    typealias genericType1 = Int 
    typealias genericType2 = String 

    func myFunc(argument1: genericType1, argument2: genericType2){ 
     // specific implementation here 
    } 
} 

NonGenericClass將在MyProtocol分機的所有功能(在這種情況下,defaultFunc(argument1: Int))。

協議MyProtocol也可以從其它協議繼承,並且那些功能的實現可以在擴展MyProtocol來限定。因此協議可以使任何符合它的類也符合另一個協議,並具有標準的實現。

但是,這具有限制,您不能從協議內指定類函數的標準覆蓋。