如何在 Swift 的便捷初始化器中调用 class 方法

How to call a class method in a convenience initializer in Swift

我正在尝试使用一个 API,其中每个对象都以不同的方式命名其 ID 字段。示例:Group.groupid、Team.teamid 等

我有一个 BaseAPIObject,它有一个接受解析的 JSON 字典的必需初始化程序和一个只接受 ID 字段的便利初始化程序(我的 属性 唯一需要的=34=]).

我已经通过添加静态又名 "class" 方法来处理不断变化的 ID 字段名称,该方法 returns ID 字段名称和 subclasses 将该函数覆盖到 return自己的字段名。

我遇到的问题是,在我的基础 class' 便利初始值设定项中,我无法在调用 self.init() 之前调用 self.dynamicType,但我需要以下结果在我可以正确构造我的对象之前那个静态 class 函数。

public class BaseAPIObject {
    var apiID: String!
    var name: String?
    var createdBy: String?
    var updatedBy: String?

    //Construct from JSONSerialization Dictionary
    required public init(_ data: [String: AnyObject]) {
        name        = data["name"] as String?
        createdBy   = data["created_by"] as String?
        updatedBy   = data["updated_by"] as String?

        super.init()

        let idName = self.dynamicType.idFieldName()
        apiID = data[idName] as String?
    }

    /// Creates an empty shell object with only the apiID set. 
    /// Useful for when you have to chase down a nested object structure
    public convenience init(id: String) {
        // THIS is what breaks! I can't call self.dynamicType here
        // How else can I call the STATIC CLASS method?
        // in ObjC this would be as simple as self.class.getIdFieldName()
        let idFieldName = self.dynamicType.getIdFieldName()
        let data = [idFieldName: id]
        self.init(data)
    }

    //This gets overridden by subclasses to return "groupid" or whatever
    class func idFieldName() -> String {
        return "id"
    }
}

问题:如何解决在 运行 init 之前调用 subclass' class function 的问题=24=]实例本身?

与其创建 class 函数来计算 ID,不如创建 init 函数。由于您已经必须为每个 subclass 创建这些函数之一,因此您并没有真正失去任何东西。 subclasses init 函数然后使用 id name.

调用 super 的 init

这是一个例子,我改变了你的组的一些属性只是为了让例子简单来说明这个概念。

public class BaseAPIObject {
    var objData: [String:String]

    required public init(_ data: [String: String]) {
        println("Data: \(data)")
        self.objData = data

    }

    public convenience init(id: String, idFieldName: String) {
        let data = [idFieldName: id]
        self.init(data)
    }
}

然后在你的子class中,概念上是这样的:

public class GroupObject: BaseAPIObject {
    public convenience init (id: String) {
        self.init(id: id, idFieldName: "group")
    }
}

let go = GroupObject(id: "foo")
println(go.objData["group"]!) //prints "foo"