【问题标题】:Failable convenience initializer with optional parameters带有可选参数的可失败的便利初始化器
【发布时间】:2015-03-16 19:52:45
【问题描述】:

我正在寻找使用带有可选参数的可失败的便利初始化程序来构造类的最佳方法。当前代码:

class Member: NSObject {

    var uid: String
    let avatarURL: NSURL
    let created: NSDate
    let email: String
    let name: String
    let provider: String

    var posts = [Post]()
    var comments = [Comment]()

    // Initialize a member with raw data
    init(uid: String, avatarURL: NSURL, created: NSDate, email: String, name: String, provider: String){
        self.uid = uid
        self.avatarURL = avatarURL
        self.created = created
        self.email = email
        self.name = name
        self.provider = provider
        super.init()
    }

    convenience init?(snapshot: FDataSnapshot){
        if let uid = snapshot.key {
            if let avatarURLString = snapshot.value["avatarURL"] as? String {
                if let avatarURL = NSURL(string: avatarURLString) {
                    if let memberCreated = snapshot.value["created"] as? NSDate {
                        if let memberEmail = snapshot.value["email"] as? String {
                            if let memberName = snapshot.value["name"] as? String {
                                if let memberProvider = snapshot.value["provider"] as? String {                                  
                                    self.init(uid: uid, avatarURL: avatarURL, created:memberCreated, email: memberEmail, name: memberName, provider: memberProvider)
                                }
                            }
                        }
                    }
                }
            }
        }
        return nil
    }
}

我需要手动初始化成员 (init) 或通过传递 Firebase 对象(方便初始化)。如果任何选项在便利初始化中失败,我希望它失败。

目前,它不会构建,因为:

类实例的所有存储属性必须在从初始化程序返回 nil 之前初始化

不知道我错过了什么。

欢迎对解决此问题的更好方法提出任何意见。

【问题讨论】:

  • guard 声明确实是很好的改进...

标签: swift


【解决方案1】:

这是 Swift 团队仍在努力改进的可失败初始化程序中的一个已知问题。正如您所说,所有属性都必须在返回nil 之前设置为某个值,因此请将它们设置为某个值(在您的情况下为""NSDate())。这有点乏味,但目前是必要的。

再清楚一点,因为有时可能有点棘手,这里有一种方法:

convenience init?(snapshot: FDataSnapshot){
    if let uid = snapshot.key {
        if let avatarURLString = snapshot.value["avatarURL"] as? String {
            if let avatarURL = NSURL(string: avatarURLString) {
                if let memberCreated = snapshot.value["created"] as? NSDate {
                    if let memberEmail = snapshot.value["email"] as? String {
                        if let memberName = snapshot.value["name"] as? String {
                            if let memberProvider = snapshot.value["provider"] as? String {
                                self.init(uid: uid, avatarURL: avatarURL, created:memberCreated, email: memberEmail, name: memberName, provider: memberProvider)
                                return
                            }
                        }
                    }
                }
            }
        }
    }

    self.init(uid: "", avatarURL: NSURL(), created: NSDate(), email: "", name: "", provider: "")
    return nil
}

(在 Swift 1.2 中,您将能够将所有这些 let's 堆叠在一起,这将使代码更加清晰,并让您在中间使用 else 而不是 return。)

关键是在便利初始化器中,你最终必须调用self.init,即使你稍后要调用return nil。 (Swift 团队知道这很烦人,但有些极端情况很难处理。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    相关资源
    最近更新 更多