"Unknown class in interface builder file" 当使用 class 时,它继承自 Storyboard 中的通用 class

"Unknown class in interface builder file" when using class which inherits from a generic class in a Storyboard

我最近从 UITableViewController 的简单继承重构了我的 class BookTableViewController,因此它现在继承自一个泛型 class FetchedResultsTableViewController<TResultType, TCellType>,它本身继承自 UITableViewController.

class 声明如下所示:

class BookTableViewController: FetchedResultsTableViewController<Book, BookTableViewCell> {

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

}

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

    // implementation here

}

在 Storyboard 中,Custom class 和 Module 都设置好了,我 可以 点击箭头跳转到 BookTableViewController 的代码class,提示故事板已正确链接到 class。但是,当我尝试 运行 应用程序时,无法识别 class - viewDidLoad() 中的代码不会 运行,并且当 [=55] 时我收到以下记录的消息=]宁我的应用程序:

Unknown class _TtC12Reading_List23BookTableViewController in Interface Builder file.

我 运行宁 XCode 7.3 (Swift 2.2)。这是 Storyboard 的限制、错误,还是我遗漏了什么?

谢谢!

更新:

经过一些实验,它似乎确实与泛型继承有关,而不是 class 的可访问性。定义了以下 classes:

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 之外的所有 classes 都在 Storyboard 的 class 自动完成中建议(尽管通用 class 也不起作用,因为没有办法在 Storyboard 中指定类型参数)。

故事板不支持直接或间接继承自通用 classes 的 classes。如果您在情节提要中使用从泛型 class 继承的 class,您将在运行时收到一个错误,指出 class 未知。

另一种方法是使用带有类型别名和扩展名的协议:

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
    }
}

class NonGenericClass 将具有 MyProtocol 扩展中的所有功能(在本例中,defaultFunc(argument1: Int))。

协议MyProtocol也可以继承自其他协议,那些功能的实现可以定义在对MyProtocol的扩展中。因此,协议可以使任何符合它的class也符合另一个协议,具有标准实现。

但是,这有一个限制,即您不能在协议中指定 class 函数的标准覆盖。

游戏有点迟了,但此信息可能对任何遇到该话题的人都有用。

实际上,据我所知,从 Swift 3 开始,故事板中对泛型的支持有些笨拙。

我已经设法编写了一个通用基础 class 扩展 UIViewController,然后约束该通用 class 的几个子 class 并在故事板中使用它们。

实际代码与下面指定的布局类似:

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 上(在单元的动态原型上)显式写入单元的 class 名称会在 table 视图单元上设置 class,并且插座可见。

但是,在运行时,当实例化包含单元格动态原型的 UIViewController 时,会显示 "unknown class in interface builder file" 警告,并且应用程序会在单元格出队时崩溃。

所以@Andew Bennet,声明:

Storyboards do not support classes which inherit from generic classes

虽然你至少是对的,但似乎不再是 100% 正确;这是我第一次成功实现这一目标,尽管只是部分实现!

有些东西有用,有些东西没用,这让我很烦恼,但总比没有好。

这在Java...

中太直截了当了