带有可选参数的可失败的便利初始化器

Posted

技术标签:

【中文标题】带有可选参数的可失败的便利初始化器【英文标题】: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 声明确实是很好的改进... 【参考方案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 团队知道这很烦人,但有些极端情况很难处理。)

【讨论】:

以上是关于带有可选参数的可失败的便利初始化器的主要内容,如果未能解决你的问题,请参考以下文章

带有 getopts 的可选选项参数

带有查询 Spring-Boot jpa 1.5 的可选参数

Javascript函数的模板,带有作为对象传递的可选和必需参数

Argparse:具有可变参数的选项的可选参数

scala:作为其他参数的函数的可选默认参数

Mathematica 中的可选命名参数