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 设置了datasource
和delegate
。您可以通过选择 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 保存当前游戏分数(不是高分)?
ios UiPickerView 与 CountryPicker 类