UIPickerView 不会显示从 NSUserDefaults 加载的数据 - 加载数据时应用程序崩溃

Posted

技术标签:

【中文标题】UIPickerView 不会显示从 NSUserDefaults 加载的数据 - 加载数据时应用程序崩溃【英文标题】:UIPickerView won't display the data loaded from NSUserDefaults - App is crashing while loading data 【发布时间】:2015-01-27 16:53:22 【问题描述】:

我第一次尝试在带有 UIPickerViews 的应用程序中使用 NSUserDefaults。但是应用程序在测试时崩溃/数据未显示在 PickerView 中。我仍然尝试自己修复它,但一些帮助会很棒。

ViewController3: 用户应该将数据保存到 NSUserDefault 的位置。因此有一个 textField 可以写下一些东西和一个“保存按钮”

class ViewController3: UIViewController, UITextFieldDelegate 

@IBOutlet weak var textField: UITextField!

...

 @IBAction func tappedAddButton(sender: AnyObject) 

    var userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()

    var exercisesList:NSMutableArray? = userDefaults.objectForKey("exercisesList") as? NSMutableArray

    var dataSet:NSMutableDictionary = NSMutableDictionary()
    dataSet.setObject(textField.text, forKey: "exercises")

    if ((exercisesList) != nil)
        var newMutableList:NSMutableArray = NSMutableArray();

        for dict:AnyObject in exercisesList!
            newMutableList.addObject(dict as NSDictionary)
        

        userDefaults.removeObjectForKey("exercisesList")
        newMutableList.addObject(dataSet)
        userDefaults.setObject(newMutableList, forKey: "exercisesList")

    else
        userDefaults.removeObjectForKey("exercisesList")
        exercisesList = NSMutableArray()
        exercisesList!.addObject(dataSet)
        userDefaults.setObject(exercisesList, forKey: "exercisesList")
    

    userDefaults.synchronize()

    self.view.endEditing(true)
    textField.text = ""


视图控制器 1: 保存的数据应该从 NSUserDefaults 加载并显示在 pickerView1 中

class ViewController: UIViewController,UIPickerViewDelegate 

@IBOutlet weak var pickerView1: UIPickerView!
@IBOutlet weak var pickerView2: UIPickerView!
@IBOutlet weak var pickerView3: UIPickerView!

var reps = [["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25"],["x"]]

var weight = [["0","1","2","3","4","5"],["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],[","],["0","25","5","75"],["kg","lbs"]]

var exercises:NSMutableArray = NSMutableArray();

override func viewDidLoad() 
    super.viewDidLoad()

    var userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()

    var exercisesListFromUserDefaults:NSMutableArray? = userDefaults.objectForKey("exercisesList") as? NSMutableArray

    if ((exercisesListFromUserDefaults) != nil)
        exercises = exercisesListFromUserDefaults!
    
    self.pickerView1.reloadAllComponents()


func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int 

    switch pickerView 
    case pickerView1:
        return 1
    case pickerView2:
        return reps.count
    case pickerView3:
        return weight.count
    default:
        assertionFailure("Unknown pickerView")
    


func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
    switch pickerView 
    case pickerView1:
        return exercises.count
    case pickerView2:
        return reps[component].count
    case pickerView3:
        return weight[component].count
    default:
        assertionFailure("Unknown pickerView")
    


func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! 
    switch pickerView 
    case pickerView1:
        return exercises[row] as String
    case pickerView2:
        return reps[component][row]
    case pickerView3:
        return weight[component][row]
    default:
        assertionFailure("Unknown pickerView")
    



【问题讨论】:

是否为您的 pickerViews 设置了数据源和委托? 我不这么认为。如何做到这一点? 【参考方案1】:

首先,确保为您的pickerViews 设置了datasourcedelegate。您可以通过选择 pickerView 并从 dataSource 拖动并委托给您的 viewController 在情节提要中设置它们:

或者您可以像这样在viewDidLoad 中设置它们:

self.pickerView1.dataSource = self
self.pickerView2.delegate = self

更新

您在 titleForRow 方法中崩溃了。我猜你的练习数组在该方法触发时没有任何数据。覆盖 viewDidLoad 并将您的代码从 viewDidAppear 移动到该方法。在选择器尝试显示数据之前,您需要在练习数组中包含数据。

我在您的viewDidAppear 方法中注意到的另一件事是,您必须在视图覆盖中做的第一件事是在您自己的代码之前调用super.viewDidAppear(animated) 之类的super。同样,您必须先在viewDidLoad 中调用super.viewDidLoad()

更新 2

在您的switch 语句中,将pickerView3 设为默认情况并去掉那些assertionFailure 行。 pickerView 委托方法需要返回值,所以这也可能会造成问题。

【讨论】:

谢谢。这样做了,但我的应用程序在更改为 ViewController3(应保存数据的位置)时不断崩溃 没有。应用程序崩溃了,我不知道为什么?也许这有帮助?:img3.fotos-hochladen.net/uploads/bildschirmfotom4qc37gapl.png 在您的屏幕截图中,在(lldb) 旁边的控制台中键入bt,然后按回车键。这将为您提供堆栈跟踪。 谢谢。做到了,但仍然行不通。也许是因为如果应用程序先启动,则未定义变量。所以 PickerView 应该返回一些不存在的东西?这可能吗? exercises 实际上最终包含练习吗?尝试在viewDidLoad 末尾添加类似println("exercises: \(self.exercises)") 的内容。【参考方案2】:

您的pickerViews 为空的原因是很可能因为您没有将它们连接到viewController1 作为数据源和委托。您可以在故事板或代码中执行此操作:

override  func viewDidLoad() 
    super.viewDidLoad()
    let pickers = [pickerView1,pickerView2,pickerView3]
    for i in 0...2 
        let pickerView : UIPickerView = pickers[i]
        pickerView.dataSource = self
        pickerView.delegate = self
    

更新 (part 3)

exercisesList 是一个字典数组。例如,您正在向练习列表中添加一个新项目:

 newMutableList.addObject(dataSet)

dataSet 的创建/定义如下:

 var dataSet:NSMutableDictionary = NSMutableDictionary()
 dataSet.setObject(textField.text, forKey: "exercises")

所以你有一个单项字典,键是“练习”。

然后在 viewController1 中解压数组并假设它填充了 字符串,而不是字典:

return exercises[row] as String

在这里,您将字典转换为字符串,该字符串崩溃了。

线索在堆栈跟踪行swift dynamic cast failed 在这些行中

 (ObjectiveC.UIPickerView, titleForRow : Swift.Int, forComponent:     
 Swift.Int) => Swift.ImplicitlyUnwrappedOptional<Swift.String>

如果您从字典键“exercises”中正确提取字符串作为值,它将起作用:

        return exercises[row]["exercises"] as String

或者,您可以使用字符串而不是字典来填充数组(因为每个条目只有一个条目)。

希望您现在可以运行它而不会崩溃!

【讨论】:

我试试看。到目前为止非常感谢。 尚未选择数据源。但是我的应用程序在使用 pickerView 更改为 ViewController 时不断崩溃。

以上是关于UIPickerView 不会显示从 NSUserDefaults 加载的数据 - 加载数据时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

NSUser Defaults 保存按钮状态并再次显示

使用 NSUser Defaults 保存当前游戏分数(不是高分)?

ios UiPickerView 与 CountryPicker 类

UIPickerView 不会立即重绘未选中的行

使用 UIButton 从 UIPickerView 向 UILabel 显示输出

从 UIPickerView 中选择的 NSTimer 在 UILabel 中显示秒数