【问题标题】:How to call a class method in a convenience initializer in Swift如何在 Swift 的便利构造器中调用类方法
【发布时间】:2015-01-28 05:42:54
【问题描述】:

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

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

我已经通过添加一个返回 ID 字段名称的静态又名“类”方法来处理不断变化的 id 字段名称,并且子类会覆盖该函数以返回它们自己的字段名称。

我遇到的问题是,在我的基类的便利初始化程序中,我不能在调用 self.init() 之前调用 self.dynamicType,但我需要该静态类函数的结果才能正确构造我的对象。

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"
    }
}

问题:如何解决在 instance 本身上运行 init 之前调用子类的 类函数 的问题?

【问题讨论】:

    标签: swift initialization


    【解决方案1】:

    不要创建类函数来计算 id,而是创建 init 函数。由于您已经必须为每个子类创建这些函数之一,因此您并没有真正失去任何东西。子类的 init 函数然后使用 id 名称调用 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)
        }
    }
    

    然后在您的子类中,从概念上讲是这样的:

    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"
    

    【讨论】:

    • 这是我昨晚最终解决问题的方法,但我仍然必须保留类函数,因为我还在 init 中以另一种我无法使用的方式使用它相同的技术。如果没有其他人能想出什么我会接受这个答案。
    猜你喜欢
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-27
    • 2014-02-17
    • 1970-01-01
    • 2019-12-08
    相关资源
    最近更新 更多