我最近从UITableViewController
的简单继承中重构了我的类BookTableViewController
,这样它现在就从UITableViewController
本身继承的泛型类FetchedResultsTableViewController<TResultType, TCellType>
继承了。
类声明如下所示:
class BookTableViewController: FetchedResultsTableViewController<Book, BookTableViewCell> {
override func viewDidLoad() {
// breakpoints in here do not catch!
}
}
class FetchedResultsTableViewController<TResultType, TCellType: UITableViewCell>:
UITableViewController, NSFetchedResultsControllerDelegate {
// implementation here
}
在序列图像板中,Custom类和Module都已设置,并且I可以单击箭头跳转到BookTableViewController
类的代码,这表明序列图像板已正确链接到该类。然而,当我尝试运行应用程序时,类无法识别——viewDidLoad()
中的代码无法运行,并且在运行应用程序的时候我收到以下日志消息:
接口生成器文件中的未知类_TtC12Reading_List23BookTableViewController。
我正在运行XCode 7.3(Swift 2.2)。这是Storyboards的限制、错误还是我错过了什么?
谢谢!
更新:
经过一些实验,它似乎确实与泛型继承有关,而不是与类的可访问性有关。定义了以下类别:
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
之外的所有类都建议在情节提要的类自动完成中使用(尽管泛型类也不起作用,因为无法在情节提要中指定类型参数)。
游戏稍微晚了一点,但这些信息可能会对任何遇到线程的人有用。
事实上,据我所知,从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 Bennet,声明:
情节提要不支持从泛型类继承的类
似乎不再是100%正确的,尽管你至少是对的;这是我第一次成功,尽管只是部分成功!
有些事情有效,有些事情无效,这让我很恼火,但总比什么都没有好。
这在Java中非常简单。。。
Storyboards不支持直接或间接继承自泛型类的类。如果在情节提要中使用从泛型类继承的类,则在运行时会出现一个错误,说明该类是未知的。
另一种选择是使用具有类型别名和扩展名的协议:
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
的扩展中定义。因此,该协议可以使符合它的任何类也符合另一个具有标准实现的协议。
但是,这有一个限制,即不能从协议中指定类函数的标准重写。