关于初始化:如何在Swift中的便捷初始化器中调用类方法

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

我尝试使用一个API,其中每个对象的ID字段名称都不同。示例:group.groupid、team.teamid等。

我有一个BaseAPIObject,它有一个接受解析的JSON字典的必需初始值设定项和一个只接受id字段(类中唯一必需的属性)的便利初始值设定项。

我已经通过添加一个静态的名为"class"的方法来处理ID字段名的更改,该方法返回ID字段名,子类重写该函数以返回自己的字段名。

我的问题是,在我的基类的便利初始值设定项中,在调用self.in i t()之前不能调用self.dynamictype,但我需要静态类函数的结果,然后才能正确地构造我的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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之前调用子类的类函数的问题?


创建init函数,而不是创建用于计算ID的类函数。由于每个子类都必须创建这些函数中的一个,所以不会真正丢失任何东西。然后,子类init函数用id名称调用super的init。

下面是一个例子,为了使这个例子更简单地说明这个概念,我改变了您组的一些属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)
    }
}

然后在您的子类中,在概念上类似这样:

1
2
3
4
5
6
7
8
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"