Swift 从类型初始化对象时出现编译器段错误

Swift Compiler SegFault when initializing Object from Type

我目前正在使用 Swift 开发 iOS 应用程序。我有一个自定义数据源,需要知道它必须提供的模型类型。我有一个自定义协议,它有一种方法。

protocol JSONModel {
    init(json: JSON)
}

然后,有几个模型实现了协议。它们都具有不同的属性,但其他方面相同。

class CurrentDownload: JSONModel {

    let someProperty: String

    required init(json: JSON) {
        someProperty = json["someProperty"].stringValue
    }

}

我的数据源有一个 属性 类型 JSONModel.Type

private let modelClass: JSONModel.Type

当我尝试初始化我的 modelClass 的新实例时,出现分段错误。模型的初始化由

完成
let model = modelClass(json: modelJSON)

不幸的是,编译器在那一行崩溃了。

Swift Compiler Error
Command failed due to signal: Segmentation fault: 11
1.  While emitting IR SIL function 

@_TFC14pyLoad_for_iOS21RemoteTableDataSourceP33_56149C9EC30967B4CD75284CC9032FEA14handleResponsefS0_FPSs9AnyObject_T_ for 'handleResponse' at RemoteTableDataSource.swift:59:13

有没有人知道如何解决这个问题或如何解决这个问题?

我相信这道题并不难。

通常 Swift 分段错误是当您尝试设置常量 (let) 的值,或尝试设置未正确声明的值时。

我可以在这里发现一个这样的例子:

required init(json: JSON) {
   bytesLeft = json["someProperty"].stringValue
}

这个例子有两处错误。您有一个(指定的)初始化程序,它在不设置 属性 someProperty 的情况下终止,并且您还没有声明变量 bytesLeft.


所以现在的问题(我 确实 之前应该发现)是 * modelClass* 不是 class(或其他可初始化类型)。不能直接访问协议,只能访问符合协议的class。编译器没有发现这一点,因为你用 .Type.

做了一些偷偷摸摸的事情

当我说访问时,我指的是函数和属性,包括初始化程序。 只有 class 可以创建 class 的实例,它以自身作为实例的类型,协议本身不能有真正的实例。 如果你仔细考虑一下,就不可能很好地定义你想在这里做什么。假设我们有协议

 protocol JSONModel {
     init(json: JSON)
 }

然后 两个 classes:

class CurrentDownload: JSONModel {
    let someProperty: String
    required init(json: JSON) {
        //Some other code perhaps.
        someProperty = json["someProperty"].stringValue
    }
}

class FutureDownload: JSONModel {
    let differentProperty: String
    required init(json: JSON) {
        //Different code.
        differentProperty = json["differentProperty"].stringValue
    }
}

而之前有人可能会争辩说

JSONModel.Type(json: JSON)

(此代码等同于您的代码)应该编译并且 运行 因为我们已经给出了 init 的实现,我们现在不能否认有混淆 - 我们应该在这里使用哪个实现?它不能选择一个,大多数人会争辩说它不应该尝试,所以它没有。

你需要做的是初始化一些class。 如果您正在寻找符合 JSONModel 的最小 class 而不是更多,则需要编写这样的 class 例如

class BasicJSONModel: JSONModel {
    let someProperty: String
    required init(json: JSON) {
        //Some other code perhaps.
        someProperty = json["someProperty"].stringValue
    }
}

然后做

private let modelClass: BasicJSONModel//.Type not needed with a class

let model = modelClass(json: modelJSON)

当然,这可能很愚蠢,可能只写

let model = BasicJSONModel(json: modelJSON)

或者 如果协议的唯一用途是这样的话,你可以写一个通用的 superclass:

class SuperJSONModel {
    let someProperty: String//This is not needed of course and you could just strip down to the init only.
    init(json: JSON) {
        //Some other code perhaps.
        someProperty = json["someProperty"].stringValue
    }
}

然后你想检查某个对象是 "conforming" 到什么是 JSONModel,你只需检查它是一个子 class SuperJSONModel.