具有自定义类类型的Swift CoreData保存属性

时间:2019-09-26 06:59:23

标签: swift core-data

我是第一次使用CoreData作为数据库来存储用户数据,以支持脱机应用程序使用。我已经为我的对象设置了数据模型,并且某些属性必须存储在其他对象类的类型中。但是,它似乎已成功保存,但是当我尝试从数据库中获取结果时它返回nil。我还查看了SQLite数据库文件,以查看存储在CoreData中的字段发生了什么情况,结果是给我nil(返回类型为Optional(Any)),并发现该属性的数据以BLOB的类型存储。

结果存储在SQLite中:

SQLite Database

最初,我的应用只能在网络可用的情况下使用,但我正试图使其支持脱机访问。但是,我一直坚持这些问题,不知道如何解决,甚至不确定自己是否做对了。

自定义对象类StudentMarkList的示例之一:

import Foundation
import UIKit
import CoreData

@objc(StudentMarkList)

class StudentMarkList: NSObject {
    var id = Int() // Student ID in DB (Primary Key)
    var paperId = String() // Paper ID which the student attended
    var studentClass = String() // Student class
    var totalMark = Int() // Total mark of the attended paper
    var allMarked = Bool() // Flag whether student's paper is all marked
    var markList = [MarkList]() // Array of marks for each question <- Custom object class of defining the structure of each question's mark

    override init() {
        super.init()
    }

    init(id:Int, paperId:String, studentClass:String, totalMark:Int, allMarked:Bool, markList:[MarkList]){
        self.id = id
        self.paperId = paperId
        self.studentClass = studentClass
        self.totalMark = totalMark
        self.allMarked = allMarked
        self.markList = markList
    }

    func save() {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }

        let managedContext = appDelegate.persistentContainer.viewContext
        managedContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

        let entity = NSEntityDescription.entity(forEntityName: "StudentMarkList", in: managedContext)!
        let studentMarkList = NSManagedObject(entity: entity, insertInto: managedContext)

        studentMarkList.setValue(self.id, forKey: "id")
        studentMarkList.setValue(self.paperId, forKey: "paperId")
        studentMarkList.setValue(self.studentClass, forKey: "studentClass")
        studentMarkList.setValue(self.totalMark, forKey: "totalMark")
        studentMarkList.setValue(self.allMarked, forKey: "allMarked")
        studentMarkList.setValue(self.markList, forKey: "markList")

        if managedContext.hasChanges {
            do {
                try managedContext.save()
            } catch let error as NSError {
                print("Could not save. \(error), \(error.userInfo)")
            }
        }
    }
}

StudentMarkList的模型:

StudentMarkList model

相应的自定义对象类MarkList

import Foundation
import UIKit
import CoreData

@objc(MarkList)

class MarkList: NSObject, NSCoding {
    func encode(with aCoder: NSCoder) {
        aCoder.encode(questionId, forKey: "questionId")
        aCoder.encode(questionNo, forKey: "questionNo")
        aCoder.encode(questionMark, forKey: "questionMark")
    }

    required init?(coder aDecoder: NSCoder) {
        guard let questionId = aDecoder.decodeObject(forKey: "questionId") as? Int,
            let questionNo = aDecoder.decodeObject(forKey: "questionNo") as? Int,
            let questionMark = aDecoder.decodeObject(forKey: "questionMark") as? String else {
                return nil
        }
        self.questionId = questionId
        self.questionNo = questionNo
        self.questionMark = questionMark
    }

    var questionId = Int()
    var questionNo = Int()
    var questionMark = String()

    override init() {
        super.init()
    }

    init(questionId: Int, questionNo: Int, questionMark: String) {
        self.questionId = questionId
        self.questionNo = questionNo
        self.questionMark = questionMark
    }

    func save() {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }

        let managedContext = appDelegate.persistentContainer.viewContext
        managedContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

        let entity = NSEntityDescription.entity(forEntityName: "MarkList", in: managedContext)!
        let markList = NSManagedObject(entity: entity, insertInto: managedContext)

        markList.setValue(self.questionId, forKey: "questionId")
        markList.setValue(self.questionNo, forKey: "questionNo")
        markList.setValue(self.questionMark, forKey: "questionMark")

        if managedContext.hasChanges {
            do {
                try managedContext.save()
            } catch let error as NSError {
                print("Could not save. \(error), \(error.userInfo)")
            }
        }
    }
}

MarkList的模型:

MarkList model

函数save()用于将实例作为相应的对象类保存到CoreData。

希望有人可以帮助我或阐明我使用CoreData的概念。谢谢!

1 个答案:

答案 0 :(得分:1)

实现将自定义类作为您的CoreData实体的属性。每个类都应视为单独的实体,并且应该通过关系管理数据链接

您必须为标记列表创建新实体,StudentMarkList将是您的父实体。

enter image description here

只需将marklist的关系添加到studentMarkList,选择您的StudentMarkList实体并创建关系,如图所示。不用担心逆运算,接下来的步骤将很明显。

enter image description here

现在选择Marklist实体并添加如下所示的关系

enter image description here

请确保将类代码源更改为使用手册

enter image description here