当前位置: 首页 > 面试题库 >

在Swift中实现可失败的初始化程序的最佳实践

何高歌
2023-03-14
问题内容

通过以下代码,我尝试定义一个简单的模型类,它是可失败的初始化器,它将(json-)字典作为参数nil如果用户名未在原始json中定义,则初始化程序应返回。

1.代码为什么不编译?错误消息显示:

从初始化器返回nil之前,必须初始化类实例的所有存储属性。

那没有道理。为什么计划返回时初始化那些属性nil

2.我的方法正确吗?或者是否有其他想法或通用模式可以实现我的目标?

class User: NSObject {

    let userName: String
    let isSuperUser: Bool = false
    let someDetails: [String]?

    init?(dictionary: NSDictionary) {
        if let value: String = dictionary["user_name"] as? String {
            userName = value
        }
        else {
           return nil
        }

        if let value: Bool = dictionary["super_user"] as? Bool {
            isSuperUser = value
        }

        someDetails = dictionary["some_details"] as? Array

        super.init()
    }
}

问题答案:

更新: 从Swift
2.2更改日志
(2016年3月21日发布):

现在,在对象已完全初始化之前,声明为失败或抛出的指定类初始化器可能分别返回nil或抛出错误。

对于Swift 2.1和更早版本:

根据Apple的文档(以及您的编译器错误),类必须nil从失败的初始化程序返回之前,初始化其所有存储的属性:

但是,对于类而言,只有在该类引入的所有存储属性都已设置为初始值并且已执行任何初始化程序委托之后,可故障初始化程序才能触发初始化失败。

注意: 它实际上适用于结构和枚举,但不适用于类。

处理在初始化程序失败之前无法初始化的存储属性的建议方法是,将它们声明为隐式展开的可选属性。

来自文档的示例

class Product {
    let name: String!
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

在上面的示例中,Product类的name属性定义为具有隐式展开的可选字符串类型(String!)。因为它是可选类型,所以这意味着name属性在初始化期间被分配特定值之前具有默认值nil。该默认值nil依次意味着Product类引入的所有属性都具有有效的初始值。结果,如果为Product设置了失败的初始化程序,则在为初始化程序内的name属性分配特定值之前,如果将其传递给空字符串,则会在初始化程序启动时触发初始化失败。

但是,在您的情况下,仅定义userName为a
String!并不能解决编译错误,因为您仍然需要担心在基类上初始化属性NSObject。幸运的是,使用userName定义为String!,您实际上可以super.init()先调用,return nil这将初始化您的NSObject基类并修复编译错误。

class User: NSObject {

    let userName: String!
    let isSuperUser: Bool = false
    let someDetails: [String]?

    init?(dictionary: NSDictionary) {
        super.init()

        if let value = dictionary["user_name"] as? String {
            self.userName = value
        }
        else {
            return nil
        }

        if let value: Bool = dictionary["super_user"] as? Bool {
            self.isSuperUser = value
        }

        self.someDetails = dictionary["some_details"] as? Array
    }
}


 类似资料:
  • 我正在将一个应用程序从Websphere迁移到jboss EAP 6.0。我已经在Jboss控制台上创建了数据源。但在我的代码中,我是这样引用的: 但是当从Jboss点击应用程序时,它会给出以下错误: 致命的http-/135.155.175.224:8080-1数据库连接。DBAccess-getDatasource():严重错误:JDBC命名服务异常:JBAS011843:实例化Initial

  • 有一个类似命名的主题,但该示例是由于用户错误而导致的错误。我相信这个例子是一个实际的XCode问题。 我正在学习一个树屋教程,本着swift2.0的精神,我在初始化程序中使用了guard语句而不是if-lets。我的代码与指令相同,只是使用了警戒语句。它有一个错误,表示“未初始化所有存储属性就从初始化程序返回”。一旦我把它改为if-let语句,它就起作用了。也许我在什么地方犯了错误,但我盯着它看了

  • 我在我的android应用程序中使用谷歌地图。我已经创建了密钥并在清单文件中添加了必要的权限。但很快我启动了应用程序,我在调试器中收到了这条消息: Google服务初始化失败,状态:10,缺少用于初始化Google服务的预期资源:“R.string.google_app_id”。可能的原因是缺少google-services.json或com.google.gms.google服务gradle插件

  • 问题内容: 直观上似乎很清楚,在Java中,实例变量初始化器是按照它们在类声明中出现的顺序执行的。 在我正在使用的JDK中,似乎确实是这种情况。例如,以下内容: 打印(换句话说,y选择的默认值z)。 实际可以保证此顺序吗?我一直在浏览JLS,找不到任何明确的确认。 问题答案: 是的。 se7 JLS在12.5执行部分中介绍了实例变量的初始化顺序: … 4.执行此类的实例初始值设定项和实例变量初始值

  • 问题内容: 我应该在这样的声明中初始化类字段吗? 还是像这样在setUp()中? 我倾向于使用第一种形式,因为它更简洁,并且允许我使用最终字段。如果我 不需要 使用setUp()方法进行设置,是否仍应使用它,为什么? 澄清: JUnit将每个测试方法实例化一次测试类。这意味着无论我在哪里声明,每次测试都会创建一次。这也意味着测试之间没有时间依赖性。因此,使用setUp()似乎没有任何优势。但是,J

  • 本文向大家介绍java中初始化MediaRecorder的实现方法,包括了java中初始化MediaRecorder的实现方法的使用技巧和注意事项,需要的朋友参考一下 java中初始化MediaRecorder 实现代码: 如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!