我尝试使用名为Sheet的自定义对象保存和检索备注数据。 但是当它运行时我遇到了崩溃。这是正确的方法,还是有其他方法可以解决这个问题?
工作表类
class Sheet {
var title = ""
var content = ""
}
这是UITableViewController的类
class NotesListTableVC: UITableViewController {
var notes = [Sheet]()
override func viewDidLoad() {
super.viewDidLoad()
if let newNotes = UserDefaults.standard.object(forKey: "notes") as? [Sheet] {
//set the instance variable to the newNotes variable
notes = newNotes
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return notes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "notesCELL", for: indexPath)
cell.textLabel!.text = notes[indexPath.row].title
return cell
}
// Add new note or opening existing note
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "editNote" {
var noteContentVC = segue.destination as! NoteContentVC
var selectedIndexPath = tableView.indexPathForSelectedRow
noteContentVC.note = notes[selectedIndexPath!.row]
}
else if segue.identifier == "newNote" {
var newEntry = Sheet()
notes.append(newEntry)
var noteContentVC = segue.destination as! NoteContentVC
noteContentVC.note = newEntry
}
saveNotesArray()
}
// Reload the table view
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
}
// Deleting notes
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
notes.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
// Save the notes
func saveNotesArray() {
// Save the newly updated array
UserDefaults.standard.set(notes, forKey: "notes")
UserDefaults.standard.synchronize()
}
}
我应该在哪里调用saveNotesArray函数?
答案 0 :(得分:4)
您正在尝试将一组自定义对象保存到UserDefaults。您的自定义对象不是property list对象您应该使用Codable来保存UserDefaults
中的非属性列表对象。
自定义类
class Sheet: Codable {
var title = ""
var content = ""
}
<强> ViewController.swift 强>
class ViewController: UIViewController {
var notes = [Sheet]()
override func viewDidLoad() {
super.viewDidLoad()
getSheets()
addSheets()
getSheets()
}
func getSheets()
{
if let storedObject: Data = UserDefaults.standard.data(forKey: "notes")
{
do
{
notes = try PropertyListDecoder().decode([Sheet].self, from: storedObject)
for note in notes
{
print(note.title)
print(note.content)
}
}
catch
{
print(error.localizedDescription)
}
}
}
func addSheets()
{
let sheet1 = Sheet()
sheet1.title = "title1"
sheet1.content = "content1"
let sheet2 = Sheet()
sheet2.title = "title1"
sheet2.content = "content1"
notes = [sheet1,sheet2]
do
{
UserDefaults.standard.set(try PropertyListEncoder().encode(notes), forKey: "notes")
UserDefaults.standard.synchronize()
}
catch
{
print(error.localizedDescription)
}
}
}
答案 1 :(得分:3)
你回答你提出的问题。
应用程序崩溃日志。
[User Defaults] Attempt to set a non-property-list object ( "Sheet.Sheet" )
官方Apple信息。
默认对象必须是属性列表 - 即(或 对于集合,实例的组合):NSData,NSString, NSNumber,NSDate,NSArray或NSDictionary。
如果要存储任何其他类型的对象,通常应该这样做 将其存档以创建NSData的实例。有关详细信息,请参阅 首选项和设置编程指南。
可能的解决方案之一:
class Sheet : NSObject, NSCoding{
var title:String?
var content:String?
func encode(with aCoder: NSCoder) {
aCoder.encodeObject(self.title, forKey: "title")
aCoder.encodeObject(self.content, forKey: "content")
}
required init?(coder aDecoder: NSCoder) {
self.title = aDecoder.decodeObject(forKey: "title") as? String
self.content = aDecoder.decodeObject(forKey: "content") as? String
}
}
保存
userDefaults.setValue(NSKeyedArchiver.archivedDataWithRootObject(sheets), forKey: "sheets")
加载
sheets = NSKeyedUnarchiver.unarchiveObjectWithData(userDefaults.objectForKey("sheets") as! NSData) as! [Sheet]
答案 2 :(得分:0)
您发布的代码尝试将一组自定义对象保存到NSUserDefaults。你不能这样做。实现NSCoding方法没有帮助。您只能在UserDefaults中存储数组,字典,字符串,数据,数字和日期等内容。
您需要将对象转换为数据(就像您在某些代码中所拥有的那样)并将该数据存储在UserDefaults中。如果需要,您甚至可以存储数据数组。
当您回读数组时,您需要取消归档数据以取回Sheet对象。
将Sheet对象更改为:
class Sheet: NSObject, NSCoding {
var title: String
var content: String
init(title: String, content: String) {
self.title = title
self.content = content
}
required convenience init(coder aDecoder: NSCoder) {
let title = aDecoder.decodeObject(forKey: "title") as! String
let content = aDecoder.decodeObject(forKey: "content") as! String
self.init(title: title, content: content)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(title, forKey: "title")
aCoder.encode(content, forKey: "content")
}
}
进入类似的函数:
func loadData() {
if let decoded = userDefaults.object(forKey: "notes") as? Data, let notes = NSKeyedUnarchiver.unarchiveObject(with: decoded) as? [Sheet] {
self.notes = notes
self.tableView.reloadData()
}
}
然后致电:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.loadData()
}
saveNotesArray可以在添加新Notes后添加:
func saveNotesArray() {
// Save the newly updated array
var userDefaults = UserDefaults.standard
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: notes)
userDefaults.set(encodedData, forKey: "notes")
userDefaults.synchronize()
}