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())
appData
是 nil
。你永远不会给它赋值。
你想要这样的东西:
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")
}
}
这避免了对 ?
的所有不必要使用,并确保您不会 运行 如果 appData
是 nil
的所有代码。
我有一个名为 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())
appData
是 nil
。你永远不会给它赋值。
你想要这样的东西:
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")
}
}
这避免了对 ?
的所有不必要使用,并确保您不会 运行 如果 appData
是 nil
的所有代码。