更新:问题和标题已根据对初始问题的回复进行了重述。
我有一个基类,它实现了用于创建新实例的泛型类方法。该类方法的简化逻辑如下
class MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MyBaseClass.init")
// Initialize base class from record
}
class func retrieveInstance<T:MyBaseClass>(name:String, callback:(T) -> ()) {
let myRecord:MyRecordType = ... // Perform fetch to get a record for name
let result = (T.self as T.Type)(myRecord) // Code currently crashes with BAD_ACCESS at this line
callback(result)
}
}
然后我实现了这个基类的子类,其逻辑类似于以下
class MySubClass : MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MySubClass.init")
// Initialize subclass from record
super.init(record)
}
}
接下来,我尝试调用泛型类方法
class AnotherClass {
func successCallback(result:MySubclass) {
// Handle callback
}
MySubClass.retrieveInstance("objectName", callback:successCallback)
}
创建类的实例时 - 标有标记崩溃位置的注释的行 - 我期望调用MySubClass
的init方法。 (这种奇怪的符号基于回复中建议的错误解决方法)
此代码不是为init
调用MySubClass
方法,而是使用BAD_ACCESS崩溃。我一直无法找到任何可以解释此崩溃的零引用或其他任何内容。
答案 0 :(得分:5)
在@rintaro最初发布的答案中得到了很多帮助,我能够解决这个问题,尽管我会在一个单独的问题上发布一些奇怪的内容。
事实证明,使用以下语法初始化泛型类型的实例需要@rintaro是完全正确的:
let result = (T.self as T.Type)(myRecord)
只要基类MyBaseClass
使用required
标记声明此初始值设定项,此方法就有效:
public class MyBaseClass {
public required init(_ record:MyRecordType) {
...
}
}
,子类MySubClass
实现了匹配的初始值设定项:
public class MySubClass : MyBaseClass {
public required init (_ record:MyRecordType) {
...
super.init(record)
}
}
当事情失败的时候,当我实际上有一个3级的类层次结构并且初始化程序层次结构通过override
进入混合时。要想象这一点,请考虑一组表示树结构中节点的类:
public class Node {
public init(_ record:MyRecordType) {
...
}
}
public class RootNode : Node {
override public init(_ record:MyRecordType) {
...
super.init(record)
}
public class func <T:RootNode>retrieveAll(success:(T) -> ()) {
// Retrieve all instances of root node subclass T, and invoke success callback with new T instance
}
}
public class ChildNode : Node {
public init(_ record:MyRecordType, parentNode:Node) {
...
super.init(record)
}
public class func <T:ChildNode>retrieveChildren(parent:Node, success:(T) -> ()) {
// Retrieve all child T instances of parent node, and invoke success callback with new T instance
{
}
问题出现在RootNode
类retrieveAll
方法的实现中。为了使其能够像@rintaro所描述的那样工作,我需要init
中的RootNode
标记required
关键字。但是因为它还覆盖了Node
的初始值设定项,所以它还需要override
个关键字。所以我尝试在声明中使用这两个关键字:
override required public init(_ record:MyRecordType) {
...
}
Swift编译器接受这个,但是当我使用它来从retrieveAll
方法中初始化一个实例时,它会崩溃并发生BAD_ACCESS。
我能够通过稍微更改NodeClass
的方法签名来解决此问题,以便其RootNode
子类不需要覆盖:
public class Node {
public init(record:MyRecordType) {
...
}
}
public class RootNode {
public required init(_ record:MyRecordType) {
...
super.init(record:record)
}
}
通过执行此解决方法,我的RootNode
子类可以正确实现所需的初始化程序,retrieveAll
中的RootNode
方法可以正确地实例化这些子类的实例。