无法在属性初始化程序中使用实例成员,将变量设置为惰性不起作用

Posted

技术标签:

【中文标题】无法在属性初始化程序中使用实例成员,将变量设置为惰性不起作用【英文标题】:Cannot use instance member within property initializer, setting the variable to lazy doesn't work 【发布时间】:2017-08-24 08:43:39 【问题描述】:

其他 SO 问题指出在变量之前使用惰性,但在这种情况下似乎不起作用。

我仍然得到这个错误,

不能在属性初始化器中使用实例成员“默认值”; 属性初始化器在“self”可用之前运行

我哪里弄错了?

class UserData

    let defaults        = UserDefaults.standard
    lazy var userDataDict    = defaults.object(forKey: "UserDataDict") as? [String: String] ?? [String: String]()


    static func setMobileNumber(mobileNumber: String)

        userDataDict["mobileNumber"]         =   mobileNumber

    

【问题讨论】:

您需要在 Swift 3 中显式类型注释:***.com/questions/38118429/…。这已在 Swift 4 中得到修复。 您不能在静态 setMobileNumber 方法中设置实例属性。 【参考方案1】:

试试这个语法:

lazy var userDataDict: [String : String] =  
    defaults.object(forKey: "UserDataDict") as? [String: String] ?? [String: String]()
()

但是,这只会设置一次userDataDict(第一次访问),之后您将看不到对UserDefaults.standard 所做的任何更改/更新。

我建议您改用计算属性

var userDataDict: [String : String]  
    guard let dict = defaults.object(forKey: "UserDataDict") as? [String: String] ?? [String: String]() else 
        return [:]
    
    return dict

(无论如何,懒惰地只做一次并不是那么昂贵的操作)

另外,我认为将UserDefaults.standard 的副本作为对象的属性没有意义;也许最好有:

// remove: 
// let defaults = UserDefaults.standard

var userDataDict: [String : String] 
    guard let dict = UserDefaults.standard.object(forKey: "UserDataDict") as? [String: String] ?? [String: String]() else 
        return [:]
    
    return dict

最后一点,就用户默认数据库而言,所有这些都使您的字典“只读”;如果您希望保留任何更改,您的属性也需要 setter

var userDataDict: [String : String] 
    get 
        guard let dict = UserDefaults.standard.object(forKey: "UserDataDict") as? [String: String] ?? [String: String]() else 
        return [:]
        
        return dict
    
    set (newValue) 
        UserDefaults.standard.set(newValue, forKey: "UserDataDict")
        UserDefaults.standard.synchronize()
    

【讨论】:

以上是关于无法在属性初始化程序中使用实例成员,将变量设置为惰性不起作用的主要内容,如果未能解决你的问题,请参考以下文章

java成员变量和局部变量的初始化和内存中的运行机制

Swift 不能在属性初始化器中使用实例成员

不能在属性初始值设定项中使用实例成员 '';属性初始化程序在 'self' 可用之前运行

SwiftUI Maps - 不能在属性初始化器中使用实例成员;属性初始化程序在 'self' 可用之前运行

iOS 开发:成员变量(属性,实例变量)的相关知识

SwiftUI CS193P - 不能在属性初始化程序中使用实例成员“卡片”;属性初始化程序在“自我”可用之前运行