Swift 将值设置为空可选产生失败

Swift setting values to empty optional yields failure

我有一个名为 DataManager 的数据 class,它看起来是这样的:

class DataManager: NSObject, NSCoding {

    var money: Double = 0
    var netWorth: Double = 0
    var businessNum: Int = 0
    var generalEPM: Int = 0
    var generalThreat: Int = 0


    override init() {

    }

    required init?(coder aDecoder: NSCoder) {
        self.money = (aDecoder.decodeDouble(forKey: "DMMoney"))
        self.netWorth = (aDecoder.decodeDouble(forKey: "DMNetWorth"))
        self.businessNum = (aDecoder.decodeInteger(forKey: "DMBusinessNum"))
        self.generalEPM = (aDecoder.decodeInteger(forKey: "DMGeneralEPM"))
        self.generalThreat = (aDecoder.decodeInteger(forKey: "DMGeneralThreat"))
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.money, forKey: "DMMoney")
        aCoder.encode(self.netWorth, forKey: "DMNetWorth")
        aCoder.encode(self.businessNum, forKey: "DMBusinessNum")
        aCoder.encode(self.generalEPM, forKey: "DMGeneralEPM")
        aCoder.encode(self.generalThreat, forKey: "DMGeneralThreat")
    }

}

然后我创建这个 class 的可选实例,因为它可以是空的(一旦用户第一次打开应用程序):

var appData:DataManager?

然后我有 2 个函数来保存和加载数据:

func saveData() {
    appData?.transformNetWorth()
    appData?.updateAllVariables()
    let encodeData: Data = NSKeyedArchiver.archivedData(withRootObject: appData)
    userDefaults.set(encodeData, forKey: "appData")
    userDefaults.synchronize()
}

func loadData() {

    if let x = userDefaults.object(forKey: "appData") as? Data {
        appData = NSKeyedUnarchiver.unarchiveObject(with: x) as? DataManager
    }
}

在我的 AppDelegate 中,一旦应用程序运行,它就会检查 DataManager 是否为空,如果是,它会为其提供以下值:

if appData == nil {
    appData?.money = 100
    appData?.businessNum = 0
    appData?.generalThreat = 0
    appData?.generalEPM = 0
    appData?.netWorth = 0
    saveData()
}

尽管如此,在发生这种情况并调用 saveData() 函数后,我尝试使用 appData!.money,但应用程序崩溃并告诉我:"Unexpectedly found nil while unwrapping...",尽管我为所有 class参数。请帮忙,因为我不知道错误在哪里。谢谢!

(当然会在尝试访问数据之前调用 loadData())

appDatanil。你永远不会给它赋值。

你想要这样的东西:

if appData == nil {
    appData = DataManager()
    appData?.money = 100
    // and the rest
}

这解决了眼前的问题,但您确实需要重构所有代码以更干净地使用可选值。

例如,将您的 saveData 更新为:

func saveData() {
    if let appData = appData {
        appData.transformNetWorth()
        appData.updateAllVariables()
        let encodeData: Data = NSKeyedArchiver.archivedData(withRootObject: appData)
        userDefaults.set(encodeData, forKey: "appData")
    }
}

这避免了对 ? 的所有不必要使用,并确保您不会 运行 如果 appDatanil 的所有代码。