I have problems to figure out how to save my string of type "RiskEntry" with NSUserDefaults. I already went through some other posts, but somehow I still did not manage to solve this particular issue.
Let me explain what the code from below does right now: I get some data from my class CustomCell in the following code snippet. Here I first check with an "identifier" which array to update with the new array value "consequences".
It all works fine and the updated array is stored in riskEntry.
However, I cannot work out how to store this with NSUserDefaults now. When I try it with e.g. riskItemDefaults.set(riskEntry, forKey: "riskItem")
I get an exception error.
Any idea what I am doing wrong here?
SWIFT3 (I removed all code not relevant for this question)
class: RiskPlan: UIViewController, UITableViewDelegate, UITableViewDataSource, CustomCellUpdaterDelegate {
var riskEntry = [RiskEntry]()
var riskItemDefaults = UserDefaults.standard
// ------ start of delegate function (receiving from CustomCell) ---------
func transferData(consequencesTranferred: String, identifier: String) {
if let index = riskEntry.index(where: {$0.title as String == identifier}) {
riskEntry[index].consequences = consequencesTranferred
} else {
print ("nothing")
}
// save with NSUserDefaults
riskItemDefaults.set(riskEntry, forKey: "riskItem")
}
}
This is my struct:
public struct RiskEntry {
let title: String
var consequences: String
}
my Custom Cell
// ---------------- delegate to transfer entered data to VC -----------------
protocol CustomCellUpdaterDelegate {
func transferData(consequencesTranferred: String, identifier: String)
}
// ---------------- start of class CellCustomized -----------------
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate, UITextViewDelegate {
var delegate: CustomCellUpdaterDelegate?
// text fields, text views and picker views
@IBOutlet weak var riskTitle: UITextView!
@IBOutlet weak var consequences: UITextView!
// ---------------- listener for text view to save input in string when editing is finished -----------------
func textViewDidEndEditing(_ textView: UITextView) {
if textView.tag == 1 {
textConsequences = consequences.text
nameIdentifier = riskTitle.text
delegate?.transferData(consequencesTranferred: self.textConsequences, identifier: nameIdentifier)
} else {
print ("nothing")
}
}
}
The closest type to a Swift struct that UserDefaults supports might be an NSDictionary. You could copy the struct elements into an Objective C NSDictionary object before saving the data.
The problem is you can't save your custom array in NSUserDefaults. To do that you should change them to NSData then save it in NSUserDefaults Here is the code I used in my project it's in swift 2 syntax and I don't think it's going be hard to convert it to swift 3
and to the get part use this combination
hope this will help
Saving objects in
UserDefaults
have very specific restrictions:You need to serialize your model, either using NSCoding or as an alternative using JSON, to map to a supported value by
UserDefaults
.I was able to program a solution based on @ahruss (How to save an array of custom struct to NSUserDefault with swift?). However, I modified it for swift 3 and it also shows how to implement this solution in a UITableView. I hope it can help someone in the future:
Add the extension from below to your structure (adjust it to your own variables)
Save the required array item like this:
let encoded = riskEntry.map { $0.encode() } riskItemDefaults.set(encoded, forKey: "consequences") riskItemDefaults.synchronize()
Load your item like this
let dataArray = riskItemDefaults.object(forKey: "consequences") as! [NSData] let savedFoo = dataArray.map { RiskEntry(data: $0)! }
If you'd like to show the saved array item in your cells, proceed this way:
cell.consequences.text = savedFoo[indexPath.row].consequences as String
Here is the complete code, modified for Swift3
structure
extension