RealmSwift 初始化程序:在 super.init 调用之前使用

Posted

技术标签:

【中文标题】RealmSwift 初始化程序:在 super.init 调用之前使用【英文标题】:RealmSwift initializer: self used before super.init call 【发布时间】:2017-06-22 22:33:38 【问题描述】:
import RealmSwift
import Realm

public class Card : Object 
    var username : String
    var firstName : String
    var lastName : String


    init?(dictionary: [String:Any]?) 
        guard let dictionary = dictionary , let username = dictionary["username"] as? String else  return else

        self.username = username
        self.firstName = firstName 
        self.lastName = lastName
    

    required public init() 
        fatalError("init() has not been implemented")
    

    required public init( realm: RLMRealm, schema: RLMObjectSchema) 
        fatalError("init(realm:schema:) has not been implemented")
    

    required public init( value: Any, schema: RLMSchema) 
       fatalError("init(value:schema:) has not been implemented")
    

我明白了:

'self' 在 super.init 调用之前使用

我的班级工作正常。添加 RealmSwift 后,我​​遇到了这些错误。如果我添加 super.init() 它会抱怨:

属性 'self.username' 未在 super.init 调用时初始化

【问题讨论】:

请注意,由 Realm 管理的 String 属性必须使用 dynamic var 声明,否则您将无法获得预期的结果。请参阅Realm's property declaration cheatsheet 了解更多信息。 谢谢 bdash 将它们修改为动态变量 【参考方案1】:

因为你的属性是字符串。

来自apple docs...

设置存储属性的初始值

在创建类或结构的实例时,类和结构必须将其所有存储的属性设置为适当的初始值。存储的属性不能处于不确定状态。 您可以在初始化程序中为存储的属性设置初始值,或者通过分配默认属性值作为属性定义的一部分。这些操作将在以下部分中描述。

你有两个选择:

1)

var username : String = ""
var firstName : String = ""
var lastName : String = ""

2)

var username : String?
var firstName : String?
var lastName : String?

【讨论】:

谢谢@faumenzella,但最初没有在我的课程中添加 :Object 它不会抱怨字符串,是因为 :Object 吗? 那是因为你没有从另一个类继承。现在您这样做了,默认情况下您继承所有初始化程序,但是通过添加至少一个,您不会。这就是你必须调用 super 的原因,因为你正在向 Object 的子类添加一个自定义初始化程序。我个人选择了另一种使用 Realm 对象的方法。我使所有属性可变,然后添加自定义设置器。我还没有找到更好的解决方案。【参考方案2】:

这里发生了几件事。

首先,当adding custom initializers to subclasses of Object 时,它们必须被声明为便利初始化器。不可能从子类中正确实现Object 所需的初始化程序,而使用便利初始化程序则无需尝试执行此操作。这也意味着您将在自定义初始化程序中委托self.init() 而不是super.init()

其次,存储的属性必须有一个初始值。如果没有初始值,Swift 编译器将不会为您的类合成初始化程序(在这种情况下,是调用基类的 init() 版本)。

最后,正如我在别处提到的,String 类型的属性必须使用 Swift 的 dynamic 修饰符声明,以允许 Realm 拦截对它们的 get/set 操作。

通过遵循这些准则,您最终会得到类似的结果:

public class Card : Object 
    dynamic var username: String = ""
    dynamic var firstName: String = ""
    dynamic var lastName: String = ""

    convenience init?(dictionary: [String:Any]?) 
        guard let dictionary = dictionary,
            let username = dictionary["username"] as? String,
            let firstName = dictionary["firstName"] as? String,
            let lastName = dictionary["lastName"] as? String
            else  return nil 

        self.init()

        self.username = username
        self.firstName = firstName
        self.lastName = lastName
    

【讨论】:

谢谢,既然我的初始 init() 是方便的 init,我想知道如何使用 init()?再一次感谢你!该错误显示为致命错误:init() 尚未实现 如果您遇到新问题,我建议您提出新问题并提供触发错误的代码。如果没有更多信息,很难推测发生了什么。 我在这里添加了一个问题***.com/questions/44728234/…

以上是关于RealmSwift 初始化程序:在 super.init 调用之前使用的主要内容,如果未能解决你的问题,请参考以下文章

带有 xCode 8 的 RealmSwift

TextField不会从RealmSwift加载

RealmSwift:没有这样的模块“RealmSwift”

Swift:在从初始化程序返回之前,不会在所有路径上调用“super.init”?

在从初始化程序返回之前,不会在所有路径上调用 super init

在从初始化程序返回之前不调用 Super.init