【发布时间】:2016-10-17 10:33:32
【问题描述】:
我有使用 NSUserDefaults 保存在“[RiskEntry]”类型数组中的数据。
让我解释一下我在这里保存的内容以及加载和保存过程在我的代码中的样子(我取出了不相关的代码,我正在使用 Swift3):
Main_ViewController
首先:在 Main_ViewController 类中,我从弹出窗口中获取了一个文本,并将其保存在一个数组中,其中 NSUserDefaults 在 riskEntry 中,键为“newTry”(这只是一个临时名称;-))-> 'func riskText( riskTextTransferred: String)'。
Plan_ViewController
第二个:当使用 segue 到达 Plan_ViewController 上的表格时,表格中会填充以“newTry”键(cell.riskTitle.text = savedTitles[indexPath.row].title as String)保存在 riskEntry 中的文本。到目前为止,这一切都很好。
CustomCell 和 Plan_ViewController
第三:当用户在单元格的文本字段(consequences.text)中输入值时,为 riskEntry 更新值后果。所以一开始,数组有一个空字符串来表示后果。现在,条目已更新为文本。
if let index = savedTitle.index(where: {$0.title.contains(identifier)}) {
savedTitle[index].consequences = consequencesTranferred
然后用键“newTry”保存新字符串。这也可以正常工作。
Main_ViewController
第四:现在我关闭 Plan_ViewController 以返回 Main_ViewController。当我现在尝试使用键“newTry”在 viewWillAppear() 中加载我的数组时,它是空的。
我做错了什么?如何在 Main_ViewController 中成功加载 Plan_ViewController 中的更新数据?
Main_ViewController
class Main_ViewController: UIViewController, UIPopoverPresentationControllerDelegate, UIGestureRecognizerDelegate {
var riskItemDefaults = UserDefaults.standard
var riskEntry = [RiskEntry]()
override func viewWillAppear(_ animated: Bool) {
if let dataArrayTitle = riskItemDefaults.object(forKey: "newTry") as? [NSData] {
var savedTitle = dataArrayTitle.map { RiskEntry(data: $0)! }
riskItemDefaults.synchronize()
// CHECKPOINT: all arrays are printed empty...
print ("savedTitle: ")
print (savedTitle)
print ("dataArrayTitle: ")
print (dataArrayTitle)
} else {
print ("nothing")
}
}
// ---------------- delegate function that creates the array items -----------------
func riskText(riskTextTransferred: String) {
// CHECKPOINT: Array is saved correctly
riskEntry = [RiskEntry(title: riskTextTransferred, consequences: "")]
let encoded = riskEntry.map {$0.encode() }
riskItemDefaults.set(encoded, forKey: "newTry")
riskItemDefaults.synchronize()
}
}
Plan_ViewController
class Plan_VC: UIViewController, UITableViewDelegate, UITableViewDataSource, CustomCellUpdaterDelegate {
@IBOutlet weak var tableView: UITableView!
var riskEntry = [RiskEntry]()
var riskItemDefaults = UserDefaults.standard
// ---------------- table settings -----------------
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// load saved data and count number of entries for numberOfSections
let dataArrayTitles = riskItemDefaults.object(forKey: "newTry") as! [NSData]
let savedTitles = dataArrayTitles.map { RiskEntry(data: $0)! }
return savedTitles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView!.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CellCustomized
cell.delegate = self
// load saved data and insert title in cell label
let dataArrayTitles = riskItemDefaults.object(forKey: "newTry") as! [NSData]
let savedTitles = dataArrayTitles.map { RiskEntry(data: $0)! }
cell.riskTitle.text = savedTitles[indexPath.row].title as String
return cell
}
// ---------------- delegate function from CustomCell -----------------
func transferData(consequencesTranferred: String, identifier: String) {
/// load entry
let dataArrayTitle = riskItemDefaults.object(forKey: "newTry") as! [NSData]
var savedTitle = dataArrayTitle.map { RiskEntry(data: $0)! }
riskItemDefaults.synchronize()
// CHECKPOINT: The entry is loaded correctly
print("loaded: ")
print(savedTitle)
/// filter entry for title contains identifier and update the empty string for consequences
if let index = savedTitle.index(where: {$0.title.contains(identifier)}) {
savedTitle[index].consequences = consequencesTranferred
let encoded = riskEntry.map { $0.encode() }
riskItemDefaults.set(encoded, forKey: "newTry")
riskItemDefaults.synchronize()
// CHECKPOINT: The entry is updated correctly
print("After updating for consequences: ")
print(savedTitle)
}else {
print ("No title with value identifier to be filtered")
}
}
}
自定义单元格
// ----------- delegate to transfer entered data to VC ------------
protocol CustomCellUpdaterDelegate {
func transferData(consequencesTranferred: String, identifier: String)
}
// ---------------- start of calss CellCustomized -----------------
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate, UITextViewDelegate {
var myColorsClass = myColors()
var myStylesClass = myStyles()
var delegate: CustomCellUpdaterDelegate?
// text fields, text views and picker views
@IBOutlet weak var riskTitle: UITextView!
@IBOutlet weak var consequences: UITextView!
var nameIdentifier = String()
var textConsequences = String()
override func awakeFromNib() {
super.awakeFromNib()
// initiate textView delegate
consequences.delegate = self
} // nib end
// ---------------- listener for text view to save input in string when editing is finished -----------------
func textViewDidEndEditing(_ textView: UITextView) {
textConsequences = consequences.text
nameIdentifier = riskTitle.text
delegate?.transferData(consequencesTranferred: self.textConsequences, identifier: nameIdentifier)
}
}
【问题讨论】:
-
基本上
NSUserDefaults是保存临时数据的错误位置,尤其是在视图控制器之间传递的数据。 -
我的数据不应该暂时保存。重新启动应用程序后数据应该仍然可用...
-
我可能误解了你的问题,但是你只是想将数据从Plan_VC传递到Main_VC,然后保存这些数据,对吗?如果是这种情况,您应该使用委托,因为 NSUserDefaults 有时间延迟来保存数据。
-
你说“解雇 Plan_ViewController”。这是怎么做到的?
-
在我的导航中有一个按钮:'func backButtonAction(_ sender:UIButton!) {dismiss(animated: true, completion: nil)}'
标签: ios arrays swift nsuserdefaults