UIPickerView无法显示从NSUserDefaults加载的数据 - 应用程序在加载数据时崩溃

时间:2015-01-27 16:53:23

标签: ios xcode swift uipickerview nsuserdefaults

我首次尝试在UIPickerViews的App中使用NSUserDefaults。但是,在测试时,应用程序崩溃/数据未在PickerView中显示。我仍然试着自己解决这个问题,但是一些帮助会很棒。

ViewController3: 用户应将数据保存到NSUserDefault。因此,有一个textField写下一些东西和一个“Savebutton”

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 = ""

}

ViewController 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")
    }
}

}

2 个答案:

答案 0 :(得分:1)

首先,确保datasource&为pickerViews设置了delegate。您可以通过选择pickerView并从dataSource拖动并委托给您的viewController来在故事板中设置它们:

screenshot

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

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

更新

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

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

更新2

switch语句中,将pickerView3设为默认大小写,并删除assertionFailure行。 pickerView委托方法期望返回值,因此这可能会使事情失效。

答案 1 :(得分:0)

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

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

exerciseList是一个字典数组。例如,您在exerciseList中添加了一个新项目:

 newMutableList.addObject(dataSet)

其中dataSet的创建/定义如下:

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

所以你有一个单项词典,用键"练习"。

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

return exercises[row] as String

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

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

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

如果您正确地从字典键中提取字符串作为值,它将起作用&#34;练习&#34;:

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

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

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