“使用继承自Storyboard中的泛型类的类时,”界面构建器文件中的未知类“

时间:2016-03-31 21:29:03

标签: ios xcode swift uikit xcode7

我最近从BookTableViewController的简单继承中重构了我的类UITableViewController,因此它现在继承自通用类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

}

在Storyboard中,自定义类和模块都已设置,我可以单击箭头跳转到BookTableViewController类的代码,表明故事板已正确链接上课。但是,当我尝试运行该应用程序时,无法识别该类 - viewDidLoad()中的代码无法运行,并且在运行我的应用程序时收到以下已记录的消息:

  

Interface Builder文件中的未知类_TtC12Reading_List23BookTableViewController。

我正在运行XCode 7.3(Swift 2.2)。这是故事板的限制,一个错误,还是我错过了什么?

谢谢!

更新

经过一些实验,它似乎与通用继承有关,而不是类的可访问性。定义了以下类:

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

2 个答案:

答案 0 :(得分:4)

游戏时间不多,但是这个信息可能会对任何碰到线程的人派上用场。

实际上,据我所知,现在,就Swift 3而言,在故事板中对泛型有一些尴尬的支持。

I&#39; VE管理写一个通用的基类延伸的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上明确地编写单元格的类名(在单元格的动态原型上)会在表格视图单元格上设置类,并且可以看到出口。

在运行时,虽然,实例化包含细胞&#39的UIViewController时; S动态原型中,&#34;界面生成器文件&#34未知类别;显示警告,并且在出列单元格时应用程序崩溃。

所以@Andew Bennet,声明:

  

故事板不支持从泛型类继承的类

似乎不再是100%的真实,尽管你至少是正确的;这是我第一次设法取消这一次,虽然只是部分的!

让我觉得有些事情有效,有些事情没有,但它总比没有好。

这在Java中非常简单......

答案 1 :(得分:2)

故事板不支持直接或间接从泛型类继承的类。如果您使用从故事板中的泛型类继承的类,则会在运行时收到错误,指出该类未知。

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

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

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