简体   繁体   English

无法在某些iPhone模拟器中保存UserDefault数组(Swift 3)

[英]cannot save UserDefault array in certain iPhone simulators (swift 3)

I'm saving an array using UserDefault and for the most part it's working incredibly great. 我正在使用UserDefault保存一个数组,并且在大多数情况下,它的工作异常出色。 However in some simulators such as iPhone 7, iPhone 5 (iOS 9.3), and iPhone 6 (iOS 9.3) the simulator crashes in the line where I try loading one of my arrays from UserDefaults. 但是,在某些模拟器中,例如iPhone 7,iPhone 5(iOS 9.3)和iPhone 6(iOS 9.3),模拟器在我尝试从UserDefaults加载数组之一的行中崩溃。

@IBAction func AddGraphComponent(_ sender: UIButton) {
    var weighText:UITextField!
    let alert = UIAlertController(title: "Enter new Weight!", message: "Please enter your Weight, followed by the date in which your weight was recorded", preferredStyle: UIAlertControllerStyle.alert)
    alert.addTextField { (weighText) in
        weighText.placeholder = "Weight"
        weighText.keyboardType = UIKeyboardType.numberPad
    }
    alert.addTextField { (dateText) in
        dateText.placeholder = "Date (MM/YY)"
    }
    let confirmAction = UIAlertAction(title: "Save", style: UIAlertActionStyle.default) { (_) in
        let field = alert.textFields![0] as? UITextField
        let weigh = alert.textFields![1] as? UITextField
        if (field?.text)! == "" || (weigh?.text)! == "" {
            let alert1 = UIAlertController(title: "Error!", message: "Please fill in BOTH fields", preferredStyle: UIAlertControllerStyle.alert)
            alert1.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert1, animated: true, completion: nil)
        }else {
            print((field?.text)!,(weigh?.text)!)
            let dataInt:Int = Int((field?.text!)!)!
            self.chartData.append(dataInt)
            self.chartLegend.append((weigh?.text)!)

            var weighting = UserDefaults.standard.array(forKey: "chartData") as! [Int]
            var dating = UserDefaults.standard.array(forKey: "chartLegend") as! [String]// this is where the error is EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP,subcode=0x0)

            weighting.append((dataInt))
            dating.append((weigh?.text)!)


            self.kUserDefault.set(weighting, forKey: "chartData")
            self.kUserDefault.set(dating, forKey: "chartLegend")
            self.kUserDefault.synchronize()

            self.lineChart.reloadData()

            print("\((dating))")
            print("\((weighting))")
        }
    }
    alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
    alert.addAction(confirmAction)
    self.present(alert, animated: true, completion: nil)
}

at the line where I write var dating = UserDefaults.standard.array(forKey: "chartLegend") as! [String] 在我写var dating = UserDefaults.standard.array(forKey: "chartLegend") as! [String] var dating = UserDefaults.standard.array(forKey: "chartLegend") as! [String] my code crashes on said device simulators. var dating = UserDefaults.standard.array(forKey: "chartLegend") as! [String]我的代码在所述设备模拟器上崩溃。 I wonder as to why this is. 我想知道为什么会这样。 Is there an error in my code, or is this a bug? 我的代码中有错误,还是一个错误? I'm using swift 3 on Xcode 8.0 我在Xcode 8.0上使用Swift 3

You are retrieving the array before you set it, which means there's a good chance it's nil , and you are force casting it with as! 您需要在设置数组之前检索数组,这意味着很有可能它为nil ,并且您用as!强制转换as! , which is something else you should avoid because in situations like this, it crashes. ,这是您应避免的其他事情,因为在这种情况下,它会崩溃。

I suggest you do var dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] ?? [String]() 我建议您将var dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] ?? [String]() var dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] ?? [String]() var dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] ?? [String]() instead to prevent the crash, and to get more familiar with optionals in general. 相反,使用var dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] ?? [String]()可以防止崩溃,并且通常可以更熟悉可选对象。

My rule is to NEVER use ! 我的规则是永远不要使用! to unwrap an optional outside of IBOutlets . IBOutlets外部打开一个可选的包装。 I use if , guard and ?? 我用ifguard?? instead. 代替。

This is happening most likely because UserDefaults doesn't find anything named 'chartData' or 'chartLegend' and then reading it as nil. 这很可能发生,因为UserDefaults找不到名为“ chartData”或“ chartLegend”的东西,然后将其读取为nil。 What you want to do is use a if let to safely check if there is a value you can receive. 您想要做的是使用if来安全检查是否可以接收到一个值。

Take a look here: 在这里看看:

if let weighting = UserDefaults.standard.array(forKey: "chartData") as? [Int] {
    //Do your stuff
    weighting.append((dataInt))
    self.kUserDefault.set(weighting, forKey: "chartData")
    print("\((weighting))")
}
if let dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] {
    //do your stuff here
    dating.append((weigh?.text)!)
    self.kUserDefault.set(dating, forKey: "chartLegend")
     print("\((dating))")
}
self.kUserDefault.synchronize()

As rmaddy commented, it is important that you do a clean install on simulator and real device before testing modified code, especially when you are dealing with read/write from storage. 正如rmaddy所说,在测试修改后的代码之前,在模拟器和真实设备上进行全新安装非常重要,尤其是在处理来自存储的读/写操作时。

Edit: 编辑:

Another approach is to use the guard statements. 另一种方法是使用保护语句。

guard let dating = UserDefaults.standard.array(forKey: "chartLegend") as? [String] 
else{ 
//dating is nil
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM