如何使用 NSUserDefaults Swift 存储自定义对象数组

How to store a custom array of objects using NSUserDefaults Swift

我是一名刚开始学习Swift制作应用程序的新手程序员。

所以我的问题是:"How can I store an array of my objects using NSUserDefaults"。本来我是看的。但是,我真的不明白他们是怎么做到的。在 youtube 上搜索确实没有成功后,我别无选择,只能问一个关于堆栈溢出的问题。 (我很犹豫,因为我是一个初学者,问一些愚蠢的问题,所以人们经常对我的问题投反对票)

所以开始了。

我正在使用 swift 制作待办事项列表。我有一个主要的 class 称为任务管理器,其中包含一组任务对象。

任务管理器(功能)

任务(功能)

所以现在,在查看了几个在线教程之后,这就是我所拥有的。 (无效)

任务管理器:原始代码

//
//  TaskManager.swift
//  ToDoList
//
//  Created by Ronak Shah on 7/5/15.
//  Copyright (c) 2015 com.ShahIndustries. All rights reserved.
//

import UIKit

var taskMgr : TaskManager = TaskManager()


class TaskManager: NSObject{
    var tasks: [Task]? = [Task]()
    var time = 1 //debug, ignore

    override init(){
        super.init()

        let taskData = NSUserDefaults.standardUserDefaults().objectForKey("tasks") as? NSData

        if let taskData = taskData {
            let taskArray = NSKeyedUnarchiver.unarchiveObjectWithData(taskData) as? [Task]

            if let taskArray = taskArray {
                tasks = taskArray
            }

        }
    }

    func addTask(taskName : String, taskDescription : String){
        var newTask = Task(taskName: taskName , taskDescription: taskDescription)

        tasks!.append(newTask)

    }

    func getTaskAtIndex(index: Int) ->Task {
        return tasks![index]
    }


    func saveData() {
        let ud = NSUserDefaults.standardUserDefaults()
        ud.setObject(NSKeyedArchiver.archivedDataWithRootObject(taskMgr), forKey: "tasks")
    }

    required init(coder aDecoder: NSCoder) {
        if let dataTasks = aDecoder.decodeObjectForKey("tasks") as? [Task] {
            self.tasks = dataTasks
        }

    }

    func encodeWithCoder(aCoder: NSCoder) {
        if let tasks = self.tasks {
            aCoder.encodeObject(tasks, forKey: "tasks")
        }
    }

    func loadData() {
        let ud = NSUserDefaults.standardUserDefaults()
        if let data = ud.objectForKey("tasks") as? NSData {
            //not sure how to get the data
        }
    }
}

任务:原始代码

//
//  Task.swift
//  ToDoList
//
//  Created by Ronak Shah on 7/5/15.
//  Copyright (c) 2015 com.ShahIndustries. All rights reserved.
//

import Foundation

class Task :NSObject{
    var name : String?
    var desc : String?

    init (taskName : String, taskDescription : String){
        self.name = taskName
        self.desc = taskDescription
    }
    required init(coder aDecoder: NSCoder) {
        if let dataDesc = aDecoder.decodeObjectForKey("desc") as? String {
            self.desc = dataDesc
        }

        if let dataTitle = aDecoder.decodeObjectForKey("name") as? String {
            self.name = dataTitle
        }
    }

    func encodeWithCoder(aCoder: NSCoder) {
        if let name = self.name {
            aCoder.encodeObject(name, forKey: "name")
        }

        if let desc = self.desc {
            aCoder.encodeObject(desc, forKey: "desc")
        }
    }
}

那么如何存储我的任务数组(任务管理器中的命名任务)?

文档说:

For NSArray and NSDictionary objects, their contents must be property list objects

属性 个列表类型中有 NSData 个。为了将您的自定义对象转换为 NSData,您必须对其进行序列化。

您正在尝试对 TaskTaskManager 对象实施归档步骤,这增加了复杂性。实现目标的最简单方法是仅归档(转换为 NSDataTask 个对象并将它们添加到数组中,然后再保存为默认值。为此,您必须将 [Task] 类型的 tasks 数组转换为 [NSData] 类型的数组。它看起来像这样。

func saveData() {
    let tasksAsData = tasks.map { task in 
        return NSKeyedArchiver.archivedDataWithRootObject(task)
    }
    let ud = NSUserDefaults.standardUserDefaults()
    ud.setObject(tasksAsData, forKey: "tasks")
}

当您取回数据时,您必须将 NSData 个对象转换为 Task 个对象。您可以通过以下方式完成。

func loadData() {
    let ud = NSUserDefaults.standardUserDefaults()
    if let data = ud.objectForKey("tasks") as? [NSData] {
        tasks = data.map { data in 
            return NSKeyedUnarchiver.unarchiveObjectWithData(data)
        }
    }
}

给你!我想你可以从这里开始。


作为旁注,我建议不要将 NSUserDefaults 用于此类目的。默认值是一种保存少量(通常)非结构化数据的简单方法。当您向任务添加更多属性时,它可能会变得很麻烦(您可能会序列化 imagedatelocation 之类的东西)。它既不 space 高效也不快速。我建议看看在 iOS 上保存数据的其他方法,例如 SQLiteCore DataRealm 或许多其他方法。