使用从情节提要中的泛型类继承的类时"Unknown class in interface builder file"



我最近从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的扩展中定义。因此,该协议可以使符合它的任何类也符合另一个具有标准实现的协议。

但是,这有一个限制,即不能从协议中指定类函数的标准重写。

最新更新